From f9a307a50b5ce67b67d2b53e8c1334ea23ffd997 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 27 Sep 2014 16:17:53 +0200 Subject: [PATCH 001/492] namespace Yosys --- Makefile | 4 +- backends/blif/blif.cc | 4 + backends/btor/btor.cc | 4 + backends/edif/edif.cc | 4 + backends/ilang/ilang_backend.cc | 6 + backends/intersynth/intersynth.cc | 3 + backends/spice/spice.cc | 4 + backends/verilog/verilog_backend.cc | 7 +- backends/verilog/verilog_backend.h | 38 -- frontends/ast/dpicall.cc | 8 + frontends/ilang/ilang_frontend.cc | 6 +- frontends/ilang/lexer.l | 2 + frontends/liberty/liberty.cc | 1 - frontends/verilog/verilog_frontend.cc | 32 +- kernel/bitpattern.h | 4 + kernel/consteval.h | 4 + kernel/log.h | 11 +- kernel/satgen.h | 5 + kernel/utils.h | 4 + kernel/yosys.h | 16 +- passes/abc/abc.cc | 4 + passes/abc/blifparse.cc | 7 +- passes/abc/blifparse.h | 7 +- passes/cmds/add.cc | 8 +- passes/cmds/connect.cc | 4 + passes/cmds/connwrappers.cc | 4 + passes/cmds/copy.cc | 4 + passes/cmds/cover.cc | 4 + passes/cmds/delete.cc | 8 +- passes/cmds/log.cc | 4 + passes/cmds/rename.cc | 4 + passes/cmds/scatter.cc | 4 + passes/cmds/scc.cc | 4 + passes/cmds/select.cc | 10 + passes/cmds/setattr.cc | 4 + passes/cmds/setundef.cc | 4 + passes/cmds/show.cc | 4 + passes/cmds/splice.cc | 4 + passes/cmds/splitnets.cc | 4 + passes/cmds/stat.cc | 265 ++++++------- passes/cmds/tee.cc | 4 + passes/cmds/trace.cc | 1 + passes/cmds/write_file.cc | 4 + passes/fsm/fsm.cc | 4 + passes/fsm/fsm_detect.cc | 4 + passes/fsm/fsm_expand.cc | 4 + passes/fsm/fsm_export.cc | 5 + passes/fsm/fsm_extract.cc | 4 + passes/fsm/fsm_info.cc | 4 + passes/fsm/fsm_map.cc | 4 + passes/fsm/fsm_opt.cc | 10 +- passes/fsm/fsm_recode.cc | 4 + passes/fsm/fsmdata.h | 7 +- passes/hierarchy/hierarchy.cc | 24 +- passes/hierarchy/submod.cc | 4 + passes/memory/memory.cc | 4 + passes/memory/memory_collect.cc | 8 +- passes/memory/memory_dff.cc | 16 +- passes/memory/memory_map.cc | 4 + passes/memory/memory_share.cc | 4 +- passes/memory/memory_unpack.cc | 8 +- passes/opt/opt.cc | 4 + passes/opt/opt_clean.cc | 20 +- passes/opt/opt_const.cc | 14 +- passes/opt/opt_muxtree.cc | 4 + passes/opt/opt_reduce.cc | 4 + passes/opt/opt_rmdff.cc | 10 +- passes/opt/opt_share.cc | 4 + passes/opt/share.cc | 2 +- passes/proc/proc.cc | 4 + passes/proc/proc_arst.cc | 15 +- passes/proc/proc_clean.cc | 15 +- passes/proc/proc_dff.cc | 14 +- passes/proc/proc_init.cc | 8 +- passes/proc/proc_mux.cc | 18 +- passes/proc/proc_rmdead.cc | 6 +- passes/sat/eval.cc | 6 +- passes/sat/expose.cc | 18 +- passes/sat/freduce.cc | 6 +- passes/sat/miter.cc | 6 +- passes/sat/sat.cc | 12 +- passes/techmap/alumacc.cc | 4 + passes/techmap/dfflibmap.cc | 4 +- passes/techmap/extract.cc | 535 +++++++++++++------------- passes/techmap/hilomap.cc | 4 + passes/techmap/iopadmap.cc | 6 +- passes/techmap/libparse.cc | 2 +- passes/techmap/libparse.h | 2 +- passes/techmap/maccmap.cc | 12 +- passes/techmap/simplemap.cc | 12 +- passes/techmap/techmap.cc | 12 +- passes/tests/test_abcloop.cc | 4 + passes/tests/test_autotb.cc | 1 + passes/tests/test_cell.cc | 4 + techlibs/common/synth.cc | 6 +- techlibs/xilinx/synth_xilinx.cc | 6 +- 96 files changed, 878 insertions(+), 585 deletions(-) delete mode 100644 backends/verilog/verilog_backend.h diff --git a/Makefile b/Makefile index 5a75320c3..00979c464 100644 --- a/Makefile +++ b/Makefile @@ -203,8 +203,8 @@ yosys: $(OBJS) kernel/version_$(GIT_REV).cc: Makefile $(P) rm -f kernel/version_*.o kernel/version_*.d kernel/version_*.cc - $(Q) echo "extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys $(YOSYS_VER) (git sha1 $(GIT_REV), $(CXX) ` \ - $(CXX) --version | tr ' ()' '\n' | grep '^[0-9]' | head -n1` $(filter -f% -m% -O% -DNDEBUG,$(CXXFLAGS)))\";" > kernel/version_$(GIT_REV).cc + $(Q) echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys $(YOSYS_VER) (git sha1 $(GIT_REV), $(CXX) ` \ + $(CXX) --version | tr ' ()' '\n' | grep '^[0-9]' | head -n1` $(filter -f% -m% -O% -DNDEBUG,$(CXXFLAGS)))\"; }" > kernel/version_$(GIT_REV).cc yosys-config: yosys-config.in $(P) $(SED) -e 's,@CXX@,$(CXX),;' -e 's,@CXXFLAGS@,$(CXXFLAGS),;' -e 's,@LDFLAGS@,$(LDFLAGS),;' -e 's,@LDLIBS@,$(LDLIBS),;' \ diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index ee12546ce..216e59fb5 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -28,6 +28,9 @@ #include "kernel/log.h" #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct BlifDumperConfig { bool icells_mode; @@ -397,3 +400,4 @@ struct BlifBackend : public Backend { } } BlifBackend; +PRIVATE_NAMESPACE_END diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 8ce5bb5ed..5bd71716e 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -30,6 +30,9 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct BtorDumperConfig { bool subckt_mode; @@ -1057,3 +1060,4 @@ struct BtorBackend : public Backend { } } BtorBackend; +PRIVATE_NAMESPACE_END diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index ccedd91d2..7f29cd41a 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -27,6 +27,9 @@ #include "kernel/log.h" #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + #define EDIF_DEF(_id) edif_names(RTLIL::unescape_id(_id), true).c_str() #define EDIF_REF(_id) edif_names(RTLIL::unescape_id(_id), false).c_str() @@ -345,3 +348,4 @@ struct EdifBackend : public Backend { } } EdifBackend; +PRIVATE_NAMESPACE_END diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index 48d818d76..19c2805ca 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -26,7 +26,9 @@ #include "kernel/yosys.h" #include +USING_YOSYS_NAMESPACE using namespace ILANG_BACKEND; +YOSYS_NAMESPACE_BEGIN void ILANG_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int width, int offset, bool autoint) { @@ -391,6 +393,9 @@ void ILANG_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl log_assert(init_autoidx == autoidx); } +YOSYS_NAMESPACE_END +PRIVATE_NAMESPACE_BEGIN + struct IlangBackend : public Backend { IlangBackend() : Backend("ilang", "write design to ilang file") { } virtual void help() @@ -510,3 +515,4 @@ struct DumpPass : public Pass { } } DumpPass; +PRIVATE_NAMESPACE_END diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc index 8502d90fc..6d4731e73 100644 --- a/backends/intersynth/intersynth.cc +++ b/backends/intersynth/intersynth.cc @@ -24,6 +24,8 @@ #include "kernel/log.h" #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN static std::string netname(std::set &conntypes_code, std::set &celltypes_code, std::set &constcells_code, RTLIL::SigSpec sig) { @@ -215,3 +217,4 @@ struct IntersynthBackend : public Backend { } } IntersynthBackend; +PRIVATE_NAMESPACE_END diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc index b057063cd..2aff94198 100644 --- a/backends/spice/spice.cc +++ b/backends/spice/spice.cc @@ -24,6 +24,9 @@ #include "kernel/log.h" #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + static void print_spice_net(std::ostream &f, RTLIL::SigBit s, std::string &neg, std::string &pos, std::string &ncpf, int &nc_counter) { if (s.wire) { @@ -231,3 +234,4 @@ struct SpiceBackend : public Backend { } } SpiceBackend; +PRIVATE_NAMESPACE_END diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index bbdbbbfaf..99430d049 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -26,7 +26,6 @@ * */ -#include "verilog_backend.h" #include "kernel/register.h" #include "kernel/celltypes.h" #include "kernel/log.h" @@ -35,7 +34,8 @@ #include #include -namespace { +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN bool norename, noattr, attr2comment, noexpr; int auto_name_counter, auto_name_offset, auto_name_digits; @@ -1016,8 +1016,6 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) active_module = NULL; } -} /* namespace */ - struct VerilogBackend : public Backend { VerilogBackend() : Backend("verilog", "write design to verilog file") { } virtual void help() @@ -1139,3 +1137,4 @@ struct VerilogBackend : public Backend { } } VerilogBackend; +PRIVATE_NAMESPACE_END diff --git a/backends/verilog/verilog_backend.h b/backends/verilog/verilog_backend.h deleted file mode 100644 index 7e6ef5ab9..000000000 --- a/backends/verilog/verilog_backend.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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. - * - * --- - * - * A simple and straightforward verilog backend. - * - * Note that RTLIL processes can't always be mapped easily to a Verilog - * process. Therefore this frontend should only be used to export a - * Verilog netlist (i.e. after the "proc" pass has converted all processes - * to logic networks and registers). - * - */ - -#ifndef VERILOG_BACKEND_H -#define VERILOG_BACKEND_H - -#include "kernel/yosys.h" - -namespace VERILOG_BACKEND { - void verilog_backend(std::ostream &f, std::vector args, RTLIL::Design *design); -} - -#endif diff --git a/frontends/ast/dpicall.cc b/frontends/ast/dpicall.cc index 2eb104fa0..e5b1ff9c0 100644 --- a/frontends/ast/dpicall.cc +++ b/frontends/ast/dpicall.cc @@ -24,6 +24,8 @@ #include #include +YOSYS_NAMESPACE_BEGIN + typedef void (*ffi_fptr) (); static ffi_fptr resolve_fn (std::string symbol_name) @@ -129,12 +131,18 @@ AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname, return newNode; } +YOSYS_NAMESPACE_END + #else /* YOSYS_ENABLE_PLUGINS */ +YOSYS_NAMESPACE_BEGIN + AST::AstNode *AST::dpi_call(const std::string&, const std::string &fname, const std::vector&, const std::vector&) { log_error("Can't call DPI function `%s': this version of yosys is built without plugin support\n", fname.c_str()); } +YOSYS_NAMESPACE_END + #endif /* YOSYS_ENABLE_PLUGINS */ diff --git a/frontends/ilang/ilang_frontend.cc b/frontends/ilang/ilang_frontend.cc index f6f926db1..7a4687a3c 100644 --- a/frontends/ilang/ilang_frontend.cc +++ b/frontends/ilang/ilang_frontend.cc @@ -26,13 +26,13 @@ #include "kernel/register.h" #include "kernel/log.h" -YOSYS_NAMESPACE_BEGIN - void rtlil_frontend_ilang_yyerror(char const *s) { - log_error("Parser error in line %d: %s\n", rtlil_frontend_ilang_yyget_lineno(), s); + YOSYS_NAMESPACE_PREFIX log_error("Parser error in line %d: %s\n", rtlil_frontend_ilang_yyget_lineno(), s); } +YOSYS_NAMESPACE_BEGIN + struct IlangFrontend : public Frontend { IlangFrontend() : Frontend("ilang", "read modules from ilang file") { } virtual void help() diff --git a/frontends/ilang/lexer.l b/frontends/ilang/lexer.l index 4109cd4bc..292321e88 100644 --- a/frontends/ilang/lexer.l +++ b/frontends/ilang/lexer.l @@ -32,6 +32,8 @@ #include "ilang_frontend.h" #include "parser.tab.h" +USING_YOSYS_NAMESPACE + #define YY_INPUT(buf,result,max_size) \ result = ILANG_FRONTEND::lexin->readsome(buf, max_size); diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index a9ab022a4..464c5c942 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -22,7 +22,6 @@ #include "kernel/log.h" YOSYS_NAMESPACE_BEGIN -using namespace PASS_DFFLIBMAP; struct token_t { char type; diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index c6d4a0b79..1e1cd852a 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -300,22 +300,6 @@ struct VerilogFrontend : public Frontend { } } VerilogFrontend; -// the yyerror function used by bison to report parser errors -void frontend_verilog_yyerror(char const *fmt, ...) -{ - va_list ap; - char buffer[1024]; - char *p = buffer; - p += snprintf(p, buffer + sizeof(buffer) - p, "Parser error in line %s:%d: ", - AST::current_filename.c_str(), frontend_verilog_yyget_lineno()); - va_start(ap, fmt); - p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap); - va_end(ap); - p += snprintf(p, buffer + sizeof(buffer) - p, "\n"); - log_error("%s", buffer); - exit(1); -} - struct VerilogDefaults : public Pass { VerilogDefaults() : Pass("verilog_defaults", "set default options for read_verilog") { } virtual void help() @@ -376,3 +360,19 @@ struct VerilogDefaults : public Pass { YOSYS_NAMESPACE_END +// the yyerror function used by bison to report parser errors +void frontend_verilog_yyerror(char const *fmt, ...) +{ + va_list ap; + char buffer[1024]; + char *p = buffer; + p += snprintf(p, buffer + sizeof(buffer) - p, "Parser error in line %s:%d: ", + YOSYS_NAMESPACE_PREFIX AST::current_filename.c_str(), frontend_verilog_yyget_lineno()); + va_start(ap, fmt); + p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap); + va_end(ap); + p += snprintf(p, buffer + sizeof(buffer) - p, "\n"); + YOSYS_NAMESPACE_PREFIX log_error("%s", buffer); + exit(1); +} + diff --git a/kernel/bitpattern.h b/kernel/bitpattern.h index 91f54593f..4d88c8e34 100644 --- a/kernel/bitpattern.h +++ b/kernel/bitpattern.h @@ -23,6 +23,8 @@ #include "kernel/log.h" #include "kernel/rtlil.h" +YOSYS_NAMESPACE_BEGIN + struct BitPatternPool { int width; @@ -133,4 +135,6 @@ struct BitPatternPool } }; +YOSYS_NAMESPACE_END + #endif diff --git a/kernel/consteval.h b/kernel/consteval.h index 2d29d3f7e..12895ec78 100644 --- a/kernel/consteval.h +++ b/kernel/consteval.h @@ -25,6 +25,8 @@ #include "kernel/celltypes.h" #include "kernel/macc.h" +YOSYS_NAMESPACE_BEGIN + struct ConstEval { RTLIL::Module *module; @@ -376,4 +378,6 @@ struct ConstEval } }; +YOSYS_NAMESPACE_END + #endif diff --git a/kernel/log.h b/kernel/log.h index e2b4db87b..2177db095 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -26,6 +26,9 @@ #include #include +// from libs/sha1/sha1.h +class SHA1; + YOSYS_NAMESPACE_BEGIN #define S__LINE__sub2(x) #x @@ -37,7 +40,7 @@ struct log_cmd_error_expection { }; extern std::vector log_files; extern std::vector log_streams; extern FILE *log_errfile; -extern class SHA1 *log_hasher; +extern SHA1 *log_hasher; extern bool log_time; extern bool log_cmd_error_throw; @@ -68,9 +71,9 @@ template static inline const char *log_id(T *obj) { void log_cell(RTLIL::Cell *cell, std::string indent = ""); -#define log_abort() log_error("Abort in %s:%d.\n", __FILE__, __LINE__) -#define log_assert(_assert_expr_) do { if (_assert_expr_) break; log_error("Assert `%s' failed in %s:%d.\n", #_assert_expr_, __FILE__, __LINE__); } while (0) -#define log_ping() log("-- %s:%d %s --\n", __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define log_abort() YOSYS_NAMESPACE_PREFIX log_error("Abort in %s:%d.\n", __FILE__, __LINE__) +#define log_assert(_assert_expr_) do { if (_assert_expr_) break; YOSYS_NAMESPACE_PREFIX log_error("Assert `%s' failed in %s:%d.\n", #_assert_expr_, __FILE__, __LINE__); } while (0) +#define log_ping() YOSYS_NAMESPACE_PREFIX log("-- %s:%d %s --\n", __FILE__, __LINE__, __PRETTY_FUNCTION__) // --------------------------------------------------- diff --git a/kernel/satgen.h b/kernel/satgen.h index 692c6e7fb..84a47c43f 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -26,6 +26,9 @@ #include "kernel/macc.h" #include "libs/ezsat/ezminisat.h" + +YOSYS_NAMESPACE_BEGIN + typedef ezMiniSAT ezDefaultSAT; struct SatGen @@ -1158,4 +1161,6 @@ struct SatGen } }; +YOSYS_NAMESPACE_END + #endif diff --git a/kernel/utils.h b/kernel/utils.h index a03caf804..264558b83 100644 --- a/kernel/utils.h +++ b/kernel/utils.h @@ -25,6 +25,8 @@ #ifndef UTILS_H #define UTILS_H +YOSYS_NAMESPACE_BEGIN + // ------------------------------------------------ // A map-like container, but you can save and restore the state // ------------------------------------------------ @@ -207,4 +209,6 @@ struct TopoSort } }; +YOSYS_NAMESPACE_END + #endif diff --git a/kernel/yosys.h b/kernel/yosys.h index b571e177f..e796919f2 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -60,18 +60,10 @@ #define PRIVATE_NAMESPACE_BEGIN namespace { #define PRIVATE_NAMESPACE_END } - -#if 0 -# define YOSYS_NAMESPACE_BEGIN namespace Yosys { -# define YOSYS_NAMESPACE_END } -# define YOSYS_NAMESPACE_PREFIX Yosys:: -# define USING_YOSYS_NAMESPACE using namespace Yosys; -#else -# define YOSYS_NAMESPACE_BEGIN -# define YOSYS_NAMESPACE_END -# define YOSYS_NAMESPACE_PREFIX -# define USING_YOSYS_NAMESPACE -#endif +#define YOSYS_NAMESPACE_BEGIN namespace Yosys { +#define YOSYS_NAMESPACE_END } +#define YOSYS_NAMESPACE_PREFIX Yosys:: +#define USING_YOSYS_NAMESPACE using namespace Yosys; #if __cplusplus >= 201103L # define OVERRIDE override diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index f1d56b23a..1a7de0663 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -53,6 +53,9 @@ #include "blifparse.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + enum class gate_type_t { G_NONE, G_FF, @@ -1207,3 +1210,4 @@ struct AbcPass : public Pass { } } AbcPass; + PRIVATE_NAMESPACE_END diff --git a/passes/abc/blifparse.cc b/passes/abc/blifparse.cc index 1fbb5720d..38151985b 100644 --- a/passes/abc/blifparse.cc +++ b/passes/abc/blifparse.cc @@ -18,9 +18,8 @@ */ #include "blifparse.h" -#include "kernel/log.h" -#include -#include + +YOSYS_NAMESPACE_BEGIN static bool read_next_line(char *&buffer, size_t &buffer_size, int &line_count, FILE *f) { @@ -240,3 +239,5 @@ error: // return NULL; } +YOSYS_NAMESPACE_END + diff --git a/passes/abc/blifparse.h b/passes/abc/blifparse.h index 272e4e645..31f5b2e5c 100644 --- a/passes/abc/blifparse.h +++ b/passes/abc/blifparse.h @@ -20,9 +20,12 @@ #ifndef ABC_BLIFPARSE #define ABC_BLIFPARSE -#include "kernel/rtlil.h" +#include "kernel/yosys.h" + +YOSYS_NAMESPACE_BEGIN extern RTLIL::Design *abc_parse_blif(FILE *f, std::string dff_name); -#endif +YOSYS_NAMESPACE_END +#endif diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc index e3fde8559..054cfc1cb 100644 --- a/passes/cmds/add.cc +++ b/passes/cmds/add.cc @@ -17,9 +17,10 @@ * */ -#include "kernel/register.h" -#include "kernel/rtlil.h" -#include "kernel/log.h" +#include "kernel/yosys.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string name, int width, bool flag_input, bool flag_output, bool flag_global) { @@ -150,3 +151,4 @@ struct AddPass : public Pass { } } AddPass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc index 30c80f732..e17c1b1c3 100644 --- a/passes/cmds/connect.cc +++ b/passes/cmds/connect.cc @@ -23,6 +23,9 @@ #include "kernel/celltypes.h" #include "kernel/log.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + static void unset_drivers(RTLIL::Design *design, RTLIL::Module *module, SigMap &sigmap, RTLIL::SigSpec &sig) { CellTypes ct(design); @@ -183,3 +186,4 @@ struct ConnectPass : public Pass { } } ConnectPass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc index aac117169..a65a63644 100644 --- a/passes/cmds/connwrappers.cc +++ b/passes/cmds/connwrappers.cc @@ -22,6 +22,9 @@ #include "kernel/rtlil.h" #include "kernel/log.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct ConnwrappersWorker { struct portdecl_t { @@ -203,3 +206,4 @@ struct ConnwrappersPass : public Pass { } } ConnwrappersPass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/copy.cc b/passes/cmds/copy.cc index be7758200..459e5b0e7 100644 --- a/passes/cmds/copy.cc +++ b/passes/cmds/copy.cc @@ -21,6 +21,9 @@ #include "kernel/rtlil.h" #include "kernel/log.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct CopyPass : public Pass { CopyPass() : Pass("copy", "copy modules in the design") { } virtual void help() @@ -53,3 +56,4 @@ struct CopyPass : public Pass { } } CopyPass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc index ac72ba53a..057f31217 100644 --- a/passes/cmds/cover.cc +++ b/passes/cmds/cover.cc @@ -25,6 +25,9 @@ #include "kernel/rtlil.h" #include "kernel/log.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct CoverPass : public Pass { CoverPass() : Pass("cover", "print code coverage counters") { } virtual void help() @@ -142,3 +145,4 @@ struct CoverPass : public Pass { } } CoverPass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc index 2a91bc9ea..8c3391e52 100644 --- a/passes/cmds/delete.cc +++ b/passes/cmds/delete.cc @@ -17,9 +17,10 @@ * */ -#include "kernel/register.h" -#include "kernel/rtlil.h" -#include "kernel/log.h" +#include "kernel/yosys.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN struct DeletePass : public Pass { DeletePass() : Pass("delete", "delete objects in the design") { } @@ -140,3 +141,4 @@ struct DeletePass : public Pass { } } DeletePass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/log.cc b/passes/cmds/log.cc index 34db0eed8..85386f3d2 100644 --- a/passes/cmds/log.cc +++ b/passes/cmds/log.cc @@ -22,6 +22,9 @@ #include "kernel/rtlil.h" #include "kernel/log.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct LogPass : public Pass { LogPass() : Pass("log", "print text and log files") { } virtual void help() @@ -76,3 +79,4 @@ struct LogPass : public Pass { } } LogPass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc index 91de364fe..1006686ef 100644 --- a/passes/cmds/rename.cc +++ b/passes/cmds/rename.cc @@ -21,6 +21,9 @@ #include "kernel/rtlil.h" #include "kernel/log.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + static void rename_in_module(RTLIL::Module *module, std::string from_name, std::string to_name) { from_name = RTLIL::escape_id(from_name); @@ -196,3 +199,4 @@ struct RenamePass : public Pass { } } RenamePass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/scatter.cc b/passes/cmds/scatter.cc index e09c00123..1cd55ecb0 100644 --- a/passes/cmds/scatter.cc +++ b/passes/cmds/scatter.cc @@ -22,6 +22,9 @@ #include "kernel/rtlil.h" #include "kernel/log.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct ScatterPass : public Pass { ScatterPass() : Pass("scatter", "add additional intermediate nets") { } virtual void help() @@ -67,3 +70,4 @@ struct ScatterPass : public Pass { } } ScatterPass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/scc.cc b/passes/cmds/scc.cc index 5224f5bc9..f7f50ab2a 100644 --- a/passes/cmds/scc.cc +++ b/passes/cmds/scc.cc @@ -29,6 +29,9 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct SccWorker { RTLIL::Design *design; @@ -297,3 +300,4 @@ struct SccPass : public Pass { } } SccPass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 4c540ca67..363687f25 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -25,6 +25,9 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + using RTLIL::id2cstr; static std::vector work_stack; @@ -795,6 +798,9 @@ static void select_stmt(RTLIL::Design *design, std::string arg) select_filter_active_mod(design, work_stack.back()); } +PRIVATE_NAMESPACE_END +YOSYS_NAMESPACE_BEGIN + // used in kernel/register.cc and maybe other locations, extern decl. in register.h void handle_extra_select_args(Pass *pass, std::vector args, size_t argidx, size_t args_size, RTLIL::Design *design) { @@ -818,6 +824,9 @@ void handle_extra_select_args(Pass *pass, std::vector args, size_t design->selection_stack.push_back(RTLIL::Selection(false)); } +YOSYS_NAMESPACE_END +PRIVATE_NAMESPACE_BEGIN + struct SelectPass : public Pass { SelectPass() : Pass("select", "modify and view the list of selected objects") { } virtual void help() @@ -1384,3 +1393,4 @@ struct LsPass : public Pass { } } LsPass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc index 029c0ec79..39c75c54e 100644 --- a/passes/cmds/setattr.cc +++ b/passes/cmds/setattr.cc @@ -21,6 +21,9 @@ #include "kernel/rtlil.h" #include "kernel/log.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct setunset_t { RTLIL::IdString name; @@ -178,3 +181,4 @@ struct SetparamPass : public Pass { } } SetparamPass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc index c72e64b80..b9a29b7d2 100644 --- a/passes/cmds/setundef.cc +++ b/passes/cmds/setundef.cc @@ -23,6 +23,9 @@ #include "kernel/rtlil.h" #include "kernel/log.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct SetundefWorker { int next_bit_mode; @@ -153,3 +156,4 @@ struct SetundefPass : public Pass { } } SetundefPass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index 2218eded2..05da47923 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -27,6 +27,9 @@ # include #endif +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + using RTLIL::id2cstr; #undef CLUSTER_CELLS_AND_PORTBOXES @@ -795,3 +798,4 @@ struct ShowPass : public Pass { } } ShowPass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc index d03aaf3b5..d3ef15ab4 100644 --- a/passes/cmds/splice.cc +++ b/passes/cmds/splice.cc @@ -24,6 +24,9 @@ #include "kernel/log.h" #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct SpliceWorker { RTLIL::Design *design; @@ -349,3 +352,4 @@ struct SplicePass : public Pass { } } SplicePass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc index 344b03fc2..a6c9fe883 100644 --- a/passes/cmds/splitnets.cc +++ b/passes/cmds/splitnets.cc @@ -22,6 +22,9 @@ #include "kernel/rtlil.h" #include "kernel/log.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct SplitnetsWorker { std::map> splitmap; @@ -183,3 +186,4 @@ struct SplitnetsPass : public Pass { } } SplitnetsPass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 19cdaa621..b21ba01ba 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -21,145 +21,145 @@ #include "kernel/celltypes.h" #include "kernel/log.h" -namespace +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct statdata_t { - struct statdata_t - { - #define STAT_INT_MEMBERS X(num_wires) X(num_wire_bits) X(num_pub_wires) X(num_pub_wire_bits) \ - X(num_memories) X(num_memory_bits) X(num_cells) X(num_processes) + #define STAT_INT_MEMBERS X(num_wires) X(num_wire_bits) X(num_pub_wires) X(num_pub_wire_bits) \ + X(num_memories) X(num_memory_bits) X(num_cells) X(num_processes) - #define X(_name) int _name; + #define X(_name) int _name; + STAT_INT_MEMBERS + #undef X + + std::map num_cells_by_type; + + statdata_t operator+(const statdata_t &other) const + { + statdata_t sum = other; + #define X(_name) sum._name += _name; STAT_INT_MEMBERS - #undef X - - std::map num_cells_by_type; - - statdata_t operator+(const statdata_t &other) const - { - statdata_t sum = other; - #define X(_name) sum._name += _name; - STAT_INT_MEMBERS - #undef X - for (auto &it : num_cells_by_type) - sum.num_cells_by_type[it.first] += it.second; - return sum; - } - - statdata_t operator*(int other) const - { - statdata_t sum = *this; - #define X(_name) sum._name *= other; - STAT_INT_MEMBERS - #undef X - for (auto &it : sum.num_cells_by_type) - it.second *= other; - return sum; - } - - statdata_t() - { - #define X(_name) _name = 0; - STAT_INT_MEMBERS - #undef X - } - - statdata_t(RTLIL::Design *design, RTLIL::Module *mod, bool width_mode) - { - #define X(_name) _name = 0; - STAT_INT_MEMBERS - #undef X - - for (auto &it : mod->wires_) - { - if (!design->selected(mod, it.second)) - continue; - - if (it.first[0] == '\\') { - num_pub_wires++; - num_pub_wire_bits += it.second->width; - } - - num_wires++; - num_wire_bits += it.second->width; - } - - for (auto &it : mod->memories) { - if (!design->selected(mod, it.second)) - continue; - num_memories++; - num_memory_bits += it.second->width * it.second->size; - } - - for (auto &it : mod->cells_) - { - if (!design->selected(mod, it.second)) - continue; - - RTLIL::IdString cell_type = it.second->type; - - if (width_mode) - { - if (cell_type.in("$not", "$pos", "$neg", - "$logic_not", "$logic_and", "$logic_or", - "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", - "$lut", "$and", "$or", "$xor", "$xnor", - "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", - "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", - "$add", "$sub", "$mul", "$div", "$mod", "$pow")) { - int width_a = it.second->hasPort("\\A") ? SIZE(it.second->getPort("\\A")) : 0; - int width_b = it.second->hasPort("\\B") ? SIZE(it.second->getPort("\\B")) : 0; - int width_y = it.second->hasPort("\\Y") ? SIZE(it.second->getPort("\\Y")) : 0; - cell_type = stringf("%s_%d", cell_type.c_str(), std::max({width_a, width_b, width_y})); - } - else if (cell_type.in("$mux", "$pmux")) - cell_type = stringf("%s_%d", cell_type.c_str(), SIZE(it.second->getPort("\\Y"))); - else if (cell_type.in("$sr", "$dff", "$dffsr", "$adff", "$dlatch", "$dlatchsr")) - cell_type = stringf("%s_%d", cell_type.c_str(), SIZE(it.second->getPort("\\Q"))); - } - - num_cells++; - num_cells_by_type[cell_type]++; - } - - for (auto &it : mod->processes) { - if (!design->selected(mod, it.second)) - continue; - num_processes++; - } - } - - void log_data() - { - log(" Number of wires: %6d\n", num_wires); - log(" Number of wire bits: %6d\n", num_wire_bits); - log(" Number of public wires: %6d\n", num_pub_wires); - log(" Number of public wire bits: %6d\n", num_pub_wire_bits); - log(" Number of memories: %6d\n", num_memories); - log(" Number of memory bits: %6d\n", num_memory_bits); - log(" Number of processes: %6d\n", num_processes); - log(" Number of cells: %6d\n", num_cells); - for (auto &it : num_cells_by_type) - log(" %-26s %6d\n", RTLIL::id2cstr(it.first), it.second); - } - }; - - statdata_t hierarchy_worker(std::map &mod_stat, RTLIL::IdString mod, int level) - { - statdata_t mod_data = mod_stat.at(mod); - std::map num_cells_by_type; - num_cells_by_type.swap(mod_data.num_cells_by_type); - + #undef X for (auto &it : num_cells_by_type) - if (mod_stat.count(it.first) > 0) { - log(" %*s%-*s %6d\n", 2*level, "", 26-2*level, RTLIL::id2cstr(it.first), it.second); - mod_data = mod_data + hierarchy_worker(mod_stat, it.first, level+1) * it.second; - mod_data.num_cells -= it.second; - } else { - mod_data.num_cells_by_type[it.first] += it.second; + sum.num_cells_by_type[it.first] += it.second; + return sum; + } + + statdata_t operator*(int other) const + { + statdata_t sum = *this; + #define X(_name) sum._name *= other; + STAT_INT_MEMBERS + #undef X + for (auto &it : sum.num_cells_by_type) + it.second *= other; + return sum; + } + + statdata_t() + { + #define X(_name) _name = 0; + STAT_INT_MEMBERS + #undef X + } + + statdata_t(RTLIL::Design *design, RTLIL::Module *mod, bool width_mode) + { + #define X(_name) _name = 0; + STAT_INT_MEMBERS + #undef X + + for (auto &it : mod->wires_) + { + if (!design->selected(mod, it.second)) + continue; + + if (it.first[0] == '\\') { + num_pub_wires++; + num_pub_wire_bits += it.second->width; } - return mod_data; + num_wires++; + num_wire_bits += it.second->width; + } + + for (auto &it : mod->memories) { + if (!design->selected(mod, it.second)) + continue; + num_memories++; + num_memory_bits += it.second->width * it.second->size; + } + + for (auto &it : mod->cells_) + { + if (!design->selected(mod, it.second)) + continue; + + RTLIL::IdString cell_type = it.second->type; + + if (width_mode) + { + if (cell_type.in("$not", "$pos", "$neg", + "$logic_not", "$logic_and", "$logic_or", + "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", + "$lut", "$and", "$or", "$xor", "$xnor", + "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", + "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", + "$add", "$sub", "$mul", "$div", "$mod", "$pow")) { + int width_a = it.second->hasPort("\\A") ? SIZE(it.second->getPort("\\A")) : 0; + int width_b = it.second->hasPort("\\B") ? SIZE(it.second->getPort("\\B")) : 0; + int width_y = it.second->hasPort("\\Y") ? SIZE(it.second->getPort("\\Y")) : 0; + cell_type = stringf("%s_%d", cell_type.c_str(), std::max({width_a, width_b, width_y})); + } + else if (cell_type.in("$mux", "$pmux")) + cell_type = stringf("%s_%d", cell_type.c_str(), SIZE(it.second->getPort("\\Y"))); + else if (cell_type.in("$sr", "$dff", "$dffsr", "$adff", "$dlatch", "$dlatchsr")) + cell_type = stringf("%s_%d", cell_type.c_str(), SIZE(it.second->getPort("\\Q"))); + } + + num_cells++; + num_cells_by_type[cell_type]++; + } + + for (auto &it : mod->processes) { + if (!design->selected(mod, it.second)) + continue; + num_processes++; + } } + + void log_data() + { + log(" Number of wires: %6d\n", num_wires); + log(" Number of wire bits: %6d\n", num_wire_bits); + log(" Number of public wires: %6d\n", num_pub_wires); + log(" Number of public wire bits: %6d\n", num_pub_wire_bits); + log(" Number of memories: %6d\n", num_memories); + log(" Number of memory bits: %6d\n", num_memory_bits); + log(" Number of processes: %6d\n", num_processes); + log(" Number of cells: %6d\n", num_cells); + for (auto &it : num_cells_by_type) + log(" %-26s %6d\n", RTLIL::id2cstr(it.first), it.second); + } +}; + +statdata_t hierarchy_worker(std::map &mod_stat, RTLIL::IdString mod, int level) +{ + statdata_t mod_data = mod_stat.at(mod); + std::map num_cells_by_type; + num_cells_by_type.swap(mod_data.num_cells_by_type); + + for (auto &it : num_cells_by_type) + if (mod_stat.count(it.first) > 0) { + log(" %*s%-*s %6d\n", 2*level, "", 26-2*level, RTLIL::id2cstr(it.first), it.second); + mod_data = mod_data + hierarchy_worker(mod_stat, it.first, level+1) * it.second; + mod_data.num_cells -= it.second; + } else { + mod_data.num_cells_by_type[it.first] += it.second; + } + + return mod_data; } struct StatPass : public Pass { @@ -243,3 +243,4 @@ struct StatPass : public Pass { } } StatPass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc index 6f80ef72c..8ef4c89e7 100644 --- a/passes/cmds/tee.cc +++ b/passes/cmds/tee.cc @@ -22,6 +22,9 @@ #include "kernel/rtlil.h" #include "kernel/log.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct TeePass : public Pass { TeePass() : Pass("tee", "redirect command output to file") { } virtual void help() @@ -86,3 +89,4 @@ struct TeePass : public Pass { } } TeePass; +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc index 09293a86b..ac61be081 100644 --- a/passes/cmds/trace.cc +++ b/passes/cmds/trace.cc @@ -20,6 +20,7 @@ #include "kernel/yosys.h" +USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct TraceMonitor : public RTLIL::Monitor diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc index 813e215ba..9f22861a5 100644 --- a/passes/cmds/write_file.cc +++ b/passes/cmds/write_file.cc @@ -20,6 +20,9 @@ #include "kernel/yosys.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct WriteFileFrontend : public Frontend { WriteFileFrontend() : Frontend("=write_file", "write a text to a file") { } virtual void help() @@ -74,3 +77,4 @@ struct WriteFileFrontend : public Frontend { } } WriteFileFrontend; +PRIVATE_NAMESPACE_END diff --git a/passes/fsm/fsm.cc b/passes/fsm/fsm.cc index 2fae76091..1e7c77727 100644 --- a/passes/fsm/fsm.cc +++ b/passes/fsm/fsm.cc @@ -22,6 +22,9 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct FsmPass : public Pass { FsmPass() : Pass("fsm", "extract and optimize finite state machines") { } virtual void help() @@ -137,3 +140,4 @@ struct FsmPass : public Pass { } } FsmPass; +PRIVATE_NAMESPACE_END diff --git a/passes/fsm/fsm_detect.cc b/passes/fsm/fsm_detect.cc index 2c846a4cf..84932e963 100644 --- a/passes/fsm/fsm_detect.cc +++ b/passes/fsm/fsm_detect.cc @@ -24,6 +24,9 @@ #include "kernel/celltypes.h" #include "fsmdata.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + static RTLIL::Module *module; static SigMap assign_map; typedef std::pair sig2driver_entry_t; @@ -189,3 +192,4 @@ struct FsmDetectPass : public Pass { } } FsmDetectPass; +PRIVATE_NAMESPACE_END diff --git a/passes/fsm/fsm_expand.cc b/passes/fsm/fsm_expand.cc index d13643911..ecd4bf762 100644 --- a/passes/fsm/fsm_expand.cc +++ b/passes/fsm/fsm_expand.cc @@ -25,6 +25,9 @@ #include "fsmdata.h" #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct FsmExpand { RTLIL::Module *module; @@ -273,3 +276,4 @@ struct FsmExpandPass : public Pass { } } FsmExpandPass; +PRIVATE_NAMESPACE_END diff --git a/passes/fsm/fsm_export.cc b/passes/fsm/fsm_export.cc index b4a6b3f7b..668fe8d1d 100644 --- a/passes/fsm/fsm_export.cc +++ b/passes/fsm/fsm_export.cc @@ -28,6 +28,9 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + /** * Convert a signal into a KISS-compatible textual representation. */ @@ -182,3 +185,5 @@ struct FsmExportPass : public Pass { } } } FsmExportPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/fsm/fsm_extract.cc b/passes/fsm/fsm_extract.cc index 451f00fcb..f3369758e 100644 --- a/passes/fsm/fsm_extract.cc +++ b/passes/fsm/fsm_extract.cc @@ -29,6 +29,9 @@ #include "kernel/celltypes.h" #include "fsmdata.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + static RTLIL::Module *module; static SigMap assign_map; typedef std::pair sig2driver_entry_t; @@ -456,3 +459,4 @@ struct FsmExtractPass : public Pass { } } FsmExtractPass; +PRIVATE_NAMESPACE_END diff --git a/passes/fsm/fsm_info.cc b/passes/fsm/fsm_info.cc index 45d68a906..4a1f1d9a2 100644 --- a/passes/fsm/fsm_info.cc +++ b/passes/fsm/fsm_info.cc @@ -25,6 +25,9 @@ #include "fsmdata.h" #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct FsmInfoPass : public Pass { FsmInfoPass() : Pass("fsm_info", "print information on finite state machines") { } virtual void help() @@ -56,3 +59,4 @@ struct FsmInfoPass : public Pass { } } FsmInfoPass; +PRIVATE_NAMESPACE_END diff --git a/passes/fsm/fsm_map.cc b/passes/fsm/fsm_map.cc index ab6d5671d..2f6ac8543 100644 --- a/passes/fsm/fsm_map.cc +++ b/passes/fsm/fsm_map.cc @@ -25,6 +25,9 @@ #include "fsmdata.h" #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + static bool pattern_is_subset(const RTLIL::Const &super_pattern, const RTLIL::Const &sub_pattern) { log_assert(SIZE(super_pattern.bits) == SIZE(sub_pattern.bits)); @@ -345,3 +348,4 @@ struct FsmMapPass : public Pass { } } FsmMapPass; +PRIVATE_NAMESPACE_END diff --git a/passes/fsm/fsm_opt.cc b/passes/fsm/fsm_opt.cc index a0e1885ec..805e3925b 100644 --- a/passes/fsm/fsm_opt.cc +++ b/passes/fsm/fsm_opt.cc @@ -25,6 +25,9 @@ #include "fsmdata.h" #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct FsmOpt { FsmData fsm_data; @@ -309,11 +312,15 @@ struct FsmOpt } }; -void FsmData::optimize_fsm(RTLIL::Cell *cell, RTLIL::Module *module) +PRIVATE_NAMESPACE_END + +void YOSYS_NAMESPACE_PREFIX FsmData::optimize_fsm(RTLIL::Cell *cell, RTLIL::Module *module) { FsmOpt fsmopt(cell, module); } +PRIVATE_NAMESPACE_BEGIN + struct FsmOptPass : public Pass { FsmOptPass() : Pass("fsm_opt", "optimize finite state machines") { } virtual void help() @@ -341,3 +348,4 @@ struct FsmOptPass : public Pass { } } FsmOptPass; +PRIVATE_NAMESPACE_END diff --git a/passes/fsm/fsm_recode.cc b/passes/fsm/fsm_recode.cc index 873ee7a16..640bed1e5 100644 --- a/passes/fsm/fsm_recode.cc +++ b/passes/fsm/fsm_recode.cc @@ -27,6 +27,9 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + static void fm_set_fsm_print(RTLIL::Cell *cell, RTLIL::Module *module, FsmData &fsm_data, const char *prefix, FILE *f) { std::string name = cell->parameters["\\NAME"].decode_string(); @@ -168,3 +171,4 @@ struct FsmRecodePass : public Pass { } } FsmRecodePass; +PRIVATE_NAMESPACE_END diff --git a/passes/fsm/fsmdata.h b/passes/fsm/fsmdata.h index 7a44dd452..17d22c86e 100644 --- a/passes/fsm/fsmdata.h +++ b/passes/fsm/fsmdata.h @@ -20,8 +20,9 @@ #ifndef FSMDATA_H #define FSMDATA_H -#include "kernel/rtlil.h" -#include "kernel/log.h" +#include "kernel/yosys.h" + +YOSYS_NAMESPACE_BEGIN struct FsmData { @@ -172,4 +173,6 @@ struct FsmData static void optimize_fsm(RTLIL::Cell *cell, RTLIL::Module *module); }; +YOSYS_NAMESPACE_END + #endif diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 14bf8d1bd..2c77a892a 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -25,15 +25,16 @@ #include #include -namespace { - struct generate_port_decl_t { - bool input, output; - RTLIL::IdString portname; - int index; - }; -} +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN -static void generate(RTLIL::Design *design, const std::vector &celltypes, const std::vector &portdecls) +struct generate_port_decl_t { + bool input, output; + RTLIL::IdString portname; + int index; +}; + +void generate(RTLIL::Design *design, const std::vector &celltypes, const std::vector &portdecls) { std::set found_celltypes; @@ -135,7 +136,7 @@ static void generate(RTLIL::Design *design, const std::vector &cell } } -static bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, std::vector &libdirs) +bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, std::vector &libdirs) { bool did_something = false; std::map> array_cells; @@ -245,7 +246,7 @@ static bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool fla return did_something; } -static void hierarchy_worker(RTLIL::Design *design, std::set &used, RTLIL::Module *mod, int indent) +void hierarchy_worker(RTLIL::Design *design, std::set &used, RTLIL::Module *mod, int indent) { if (used.count(mod) > 0) return; @@ -262,7 +263,7 @@ static void hierarchy_worker(RTLIL::Design *design, std::set &us } } -static void hierarchy(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib, bool first_pass) +void hierarchy(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib, bool first_pass) { std::set used; hierarchy_worker(design, used, top, 0); @@ -528,3 +529,4 @@ struct HierarchyPass : public Pass { } } HierarchyPass; +PRIVATE_NAMESPACE_END diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 1b03ab555..68a441f40 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -24,6 +24,9 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct SubmodWorker { CellTypes ct; @@ -347,3 +350,4 @@ struct SubmodPass : public Pass { } } SubmodPass; +PRIVATE_NAMESPACE_END diff --git a/passes/memory/memory.cc b/passes/memory/memory.cc index fc3095535..502e21022 100644 --- a/passes/memory/memory.cc +++ b/passes/memory/memory.cc @@ -22,6 +22,9 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct MemoryPass : public Pass { MemoryPass() : Pass("memory", "translate memories to basic cells") { } virtual void help() @@ -73,3 +76,4 @@ struct MemoryPass : public Pass { } } MemoryPass; +PRIVATE_NAMESPACE_END diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc index 9c670f00f..546306822 100644 --- a/passes/memory/memory_collect.cc +++ b/passes/memory/memory_collect.cc @@ -23,7 +23,10 @@ #include #include -static bool memcells_cmp(RTLIL::Cell *a, RTLIL::Cell *b) +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +bool memcells_cmp(RTLIL::Cell *a, RTLIL::Cell *b) { if (a->type == "$memrd" && b->type == "$memrd") return a->name < b->name; @@ -32,7 +35,7 @@ static bool memcells_cmp(RTLIL::Cell *a, RTLIL::Cell *b) return a->parameters.at("\\PRIORITY").as_int() < b->parameters.at("\\PRIORITY").as_int(); } -static void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) +void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) { log("Collecting $memrd and $memwr for memory `%s' in module `%s':\n", memory->name.c_str(), module->name.c_str()); @@ -205,3 +208,4 @@ struct MemoryCollectPass : public Pass { } } MemoryCollectPass; +PRIVATE_NAMESPACE_END diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc index 302ab3abf..d3cc681a2 100644 --- a/passes/memory/memory_dff.cc +++ b/passes/memory/memory_dff.cc @@ -22,13 +22,16 @@ #include #include -static void normalize_sig(RTLIL::Module *module, RTLIL::SigSpec &sig) +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +void normalize_sig(RTLIL::Module *module, RTLIL::SigSpec &sig) { for (auto &conn : module->connections()) sig.replace(conn.first, conn.second); } -static bool find_sig_before_dff(RTLIL::Module *module, std::vector &dff_cells, RTLIL::SigSpec &sig, RTLIL::SigSpec &clk, bool &clk_polarity, bool after = false) +bool find_sig_before_dff(RTLIL::Module *module, std::vector &dff_cells, RTLIL::SigSpec &sig, RTLIL::SigSpec &clk, bool &clk_polarity, bool after = false) { normalize_sig(module, sig); @@ -66,7 +69,7 @@ static bool find_sig_before_dff(RTLIL::Module *module, std::vector return true; } -static void handle_wr_cell(RTLIL::Module *module, std::vector &dff_cells, RTLIL::Cell *cell) +void handle_wr_cell(RTLIL::Module *module, std::vector &dff_cells, RTLIL::Cell *cell) { log("Checking cell `%s' in module `%s': ", cell->name.c_str(), module->name.c_str()); @@ -105,7 +108,7 @@ static void handle_wr_cell(RTLIL::Module *module, std::vector &dff log("no (compatible) $dff found.\n"); } -static void disconnect_dff(RTLIL::Module *module, RTLIL::SigSpec sig) +void disconnect_dff(RTLIL::Module *module, RTLIL::SigSpec sig) { normalize_sig(module, sig); sig.sort_and_unify(); @@ -123,7 +126,7 @@ static void disconnect_dff(RTLIL::Module *module, RTLIL::SigSpec sig) } } -static void handle_rd_cell(RTLIL::Module *module, std::vector &dff_cells, RTLIL::Cell *cell) +void handle_rd_cell(RTLIL::Module *module, std::vector &dff_cells, RTLIL::Cell *cell) { log("Checking cell `%s' in module `%s': ", cell->name.c_str(), module->name.c_str()); @@ -161,7 +164,7 @@ static void handle_rd_cell(RTLIL::Module *module, std::vector &dff log("no (compatible) $dff found.\n"); } -static void handle_module(RTLIL::Module *module, bool flag_wr_only) +void handle_module(RTLIL::Module *module, bool flag_wr_only) { std::vector dff_cells; @@ -216,3 +219,4 @@ struct MemoryDffPass : public Pass { } } MemoryDffPass; +PRIVATE_NAMESPACE_END diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc index eecb6f35d..449604c1a 100644 --- a/passes/memory/memory_map.cc +++ b/passes/memory/memory_map.cc @@ -23,6 +23,9 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct MemoryMapWorker { RTLIL::Design *design; @@ -339,3 +342,4 @@ struct MemoryMapPass : public Pass { } } MemoryMapPass; +PRIVATE_NAMESPACE_END diff --git a/passes/memory/memory_share.cc b/passes/memory/memory_share.cc index 3ae0cd2c7..f77b304b4 100644 --- a/passes/memory/memory_share.cc +++ b/passes/memory/memory_share.cc @@ -22,9 +22,10 @@ #include "kernel/sigtools.h" #include "kernel/modtools.h" +USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -static bool memcells_cmp(RTLIL::Cell *a, RTLIL::Cell *b) +bool memcells_cmp(RTLIL::Cell *a, RTLIL::Cell *b) { if (a->type == "$memrd" && b->type == "$memrd") return a->name < b->name; @@ -741,4 +742,3 @@ struct MemorySharePass : public Pass { } MemorySharePass; PRIVATE_NAMESPACE_END - diff --git a/passes/memory/memory_unpack.cc b/passes/memory/memory_unpack.cc index 5a4c4eac9..e650facb4 100644 --- a/passes/memory/memory_unpack.cc +++ b/passes/memory/memory_unpack.cc @@ -23,7 +23,10 @@ #include #include -static void handle_memory(RTLIL::Module *module, RTLIL::Cell *memory) +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +void handle_memory(RTLIL::Module *module, RTLIL::Cell *memory) { log("Creating $memrd and $memwr for memory `%s' in module `%s':\n", memory->name.c_str(), module->name.c_str()); @@ -76,7 +79,7 @@ static void handle_memory(RTLIL::Module *module, RTLIL::Cell *memory) module->remove(memory); } -static void handle_module(RTLIL::Design *design, RTLIL::Module *module) +void handle_module(RTLIL::Design *design, RTLIL::Module *module) { std::vector memcells; for (auto &cell_it : module->cells_) @@ -107,3 +110,4 @@ struct MemoryUnpackPass : public Pass { } } MemoryUnpackPass; +PRIVATE_NAMESPACE_END diff --git a/passes/opt/opt.cc b/passes/opt/opt.cc index b20521d1e..ea454b333 100644 --- a/passes/opt/opt.cc +++ b/passes/opt/opt.cc @@ -22,6 +22,9 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct OptPass : public Pass { OptPass() : Pass("opt", "perform simple optimizations") { } virtual void help() @@ -142,3 +145,4 @@ struct OptPass : public Pass { } } OptPass; +PRIVATE_NAMESPACE_END diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 5046752f9..d589518aa 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -25,12 +25,15 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + using RTLIL::id2cstr; -static CellTypes ct, ct_reg, ct_all; -static int count_rm_cells, count_rm_wires; +CellTypes ct, ct_reg, ct_all; +int count_rm_cells, count_rm_wires; -static void rmunused_module_cells(RTLIL::Module *module, bool verbose) +void rmunused_module_cells(RTLIL::Module *module, bool verbose) { SigMap assign_map(module); std::set> queue, unused; @@ -93,7 +96,7 @@ static void rmunused_module_cells(RTLIL::Module *module, bool verbose) } } -static int count_nontrivial_wire_attrs(RTLIL::Wire *w) +int count_nontrivial_wire_attrs(RTLIL::Wire *w) { int count = w->attributes.size(); count -= w->attributes.count("\\src"); @@ -101,7 +104,7 @@ static int count_nontrivial_wire_attrs(RTLIL::Wire *w) return count; } -static bool compare_signals(RTLIL::SigBit &s1, RTLIL::SigBit &s2, SigPool ®s, SigPool &conns, std::set &direct_wires) +bool compare_signals(RTLIL::SigBit &s1, RTLIL::SigBit &s2, SigPool ®s, SigPool &conns, std::set &direct_wires) { RTLIL::Wire *w1 = s1.wire; RTLIL::Wire *w2 = s2.wire; @@ -136,7 +139,7 @@ static bool compare_signals(RTLIL::SigBit &s1, RTLIL::SigBit &s2, SigPool ®s, return w2->name < w1->name; } -static bool check_public_name(RTLIL::IdString id) +bool check_public_name(RTLIL::IdString id) { const std::string &id_str = id.str(); if (id_str[0] == '$') @@ -148,7 +151,7 @@ static bool check_public_name(RTLIL::IdString id) return true; } -static void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbose) +void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbose) { SigPool register_signals; SigPool connected_signals; @@ -285,7 +288,7 @@ static void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool log(" removed %d unused temporary wires.\n", del_wires_count); } -static void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose) +void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose) { if (verbose) log("Finding unused cells or wires in module %s..\n", module->name.c_str()); @@ -419,3 +422,4 @@ struct CleanPass : public Pass { } } CleanPass; +PRIVATE_NAMESPACE_END diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc index f9b78c053..7c9fca961 100644 --- a/passes/opt/opt_const.cc +++ b/passes/opt/opt_const.cc @@ -26,9 +26,12 @@ #include #include -static bool did_something; +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN -static void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) +bool did_something; + +void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) { CellTypes ct(design); SigMap sigmap(module); @@ -70,7 +73,7 @@ static void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) } } -static void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, std::string info, std::string out_port, RTLIL::SigSpec out_val) +void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, std::string info, std::string out_port, RTLIL::SigSpec out_val) { RTLIL::SigSpec Y = cell->getPort(out_port); out_val.extend_u0(Y.size(), false); @@ -85,7 +88,7 @@ static void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell did_something = true; } -static bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutative, SigMap &sigmap) +bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutative, SigMap &sigmap) { std::string b_name = cell->hasPort("\\B") ? "\\B" : "\\A"; @@ -183,7 +186,7 @@ static bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool com return true; } -static void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool consume_x, bool mux_undef, bool mux_bool, bool do_fine, bool keepdc) +void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool consume_x, bool mux_undef, bool mux_bool, bool do_fine, bool keepdc) { if (!design->selected(module)) return; @@ -1006,3 +1009,4 @@ struct OptConstPass : public Pass { } } OptConstPass; +PRIVATE_NAMESPACE_END diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 2c5dcf668..88ae43f0e 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -25,6 +25,9 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + using RTLIL::id2cstr; struct OptMuxtreeWorker @@ -438,3 +441,4 @@ struct OptMuxtreePass : public Pass { } } OptMuxtreePass; +PRIVATE_NAMESPACE_END diff --git a/passes/opt/opt_reduce.cc b/passes/opt/opt_reduce.cc index e9e2bb399..302deb9bd 100644 --- a/passes/opt/opt_reduce.cc +++ b/passes/opt/opt_reduce.cc @@ -25,6 +25,9 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct OptReduceWorker { RTLIL::Design *design; @@ -378,3 +381,4 @@ struct OptReducePass : public Pass { } } OptReducePass; +PRIVATE_NAMESPACE_END diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 48f406f65..c7e92ddc1 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -23,10 +23,13 @@ #include #include -static SigMap assign_map, dff_init_map; -static SigSet mux_drivers; +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN -static bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) +SigMap assign_map, dff_init_map; +SigSet mux_drivers; + +bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) { RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r; RTLIL::Const val_cp, val_rp, val_rv; @@ -215,3 +218,4 @@ struct OptRmdffPass : public Pass { } } OptRmdffPass; +PRIVATE_NAMESPACE_END diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index 4b76a5a2d..33115349c 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -28,6 +28,9 @@ #define USE_CELL_HASH_CACHE +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct OptShareWorker { RTLIL::Design *design; @@ -319,3 +322,4 @@ struct OptSharePass : public Pass { } } OptSharePass; +PRIVATE_NAMESPACE_END diff --git a/passes/opt/share.cc b/passes/opt/share.cc index 74b049bb6..03f6527c0 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -23,6 +23,7 @@ #include "kernel/modtools.h" #include "kernel/utils.h" +USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct ShareWorkerConfig @@ -1168,4 +1169,3 @@ struct SharePass : public Pass { } SharePass; PRIVATE_NAMESPACE_END - diff --git a/passes/proc/proc.cc b/passes/proc/proc.cc index 36d4141bb..30efbab4b 100644 --- a/passes/proc/proc.cc +++ b/passes/proc/proc.cc @@ -22,6 +22,9 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct ProcPass : public Pass { ProcPass() : Pass("proc", "translate processes to netlists") { } virtual void help() @@ -81,3 +84,4 @@ struct ProcPass : public Pass { } } ProcPass; +PRIVATE_NAMESPACE_END diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index f11b328f0..d7cb38bcd 100644 --- a/passes/proc/proc_arst.cc +++ b/passes/proc/proc_arst.cc @@ -23,10 +23,14 @@ #include #include -// defined in proc_clean.cc +YOSYS_NAMESPACE_BEGIN extern void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int max_depth); +YOSYS_NAMESPACE_END -static bool check_signal(RTLIL::Module *mod, RTLIL::SigSpec signal, RTLIL::SigSpec ref, bool &polarity) +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +bool check_signal(RTLIL::Module *mod, RTLIL::SigSpec signal, RTLIL::SigSpec ref, bool &polarity) { if (signal.size() != 1) return false; @@ -81,7 +85,7 @@ static bool check_signal(RTLIL::Module *mod, RTLIL::SigSpec signal, RTLIL::SigSp return false; } -static void apply_const(RTLIL::Module *mod, const RTLIL::SigSpec rspec, RTLIL::SigSpec &rval, RTLIL::CaseRule *cs, RTLIL::SigSpec const_sig, bool polarity, bool unknown) +void apply_const(RTLIL::Module *mod, const RTLIL::SigSpec rspec, RTLIL::SigSpec &rval, RTLIL::CaseRule *cs, RTLIL::SigSpec const_sig, bool polarity, bool unknown) { for (auto &action : cs->actions) { if (unknown) @@ -114,7 +118,7 @@ static void apply_const(RTLIL::Module *mod, const RTLIL::SigSpec rspec, RTLIL::S } } -static void eliminate_const(RTLIL::Module *mod, RTLIL::CaseRule *cs, RTLIL::SigSpec const_sig, bool polarity) +void eliminate_const(RTLIL::Module *mod, RTLIL::CaseRule *cs, RTLIL::SigSpec const_sig, bool polarity) { for (auto sw : cs->switches) { bool this_polarity = polarity; @@ -149,7 +153,7 @@ static void eliminate_const(RTLIL::Module *mod, RTLIL::CaseRule *cs, RTLIL::SigS } } -static void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map) +void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map) { restart_proc_arst: if (proc->root_case.switches.size() != 1) @@ -280,3 +284,4 @@ struct ProcArstPass : public Pass { } } ProcArstPass; +PRIVATE_NAMESPACE_END diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc index 1e3dd9ce7..82716cd06 100644 --- a/passes/proc/proc_clean.cc +++ b/passes/proc/proc_clean.cc @@ -22,8 +22,12 @@ #include #include -extern void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did_something, int &count, int max_depth); +YOSYS_NAMESPACE_BEGIN extern void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int max_depth); +YOSYS_NAMESPACE_END + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did_something, int &count, int max_depth) { @@ -89,6 +93,9 @@ void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did } } +PRIVATE_NAMESPACE_END +YOSYS_NAMESPACE_BEGIN + void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int max_depth) { for (size_t i = 0; i < cs->actions.size(); i++) { @@ -109,7 +116,10 @@ void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int m } } -static void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count) +YOSYS_NAMESPACE_END +PRIVATE_NAMESPACE_BEGIN + +void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count) { int count = 0; bool did_something = true; @@ -174,3 +184,4 @@ struct ProcCleanPass : public Pass { } } ProcCleanPass; +PRIVATE_NAMESPACE_END diff --git a/passes/proc/proc_dff.cc b/passes/proc/proc_dff.cc index e69e8023d..b632cdabb 100644 --- a/passes/proc/proc_dff.cc +++ b/passes/proc/proc_dff.cc @@ -25,7 +25,10 @@ #include #include -static RTLIL::SigSpec find_any_lvalue(const RTLIL::Process *proc) +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +RTLIL::SigSpec find_any_lvalue(const RTLIL::Process *proc) { RTLIL::SigSpec lvalue; @@ -50,7 +53,7 @@ static RTLIL::SigSpec find_any_lvalue(const RTLIL::Process *proc) return lvalue; } -static void gen_dffsr_complex(RTLIL::Module *mod, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, RTLIL::SigSpec clk, bool clk_polarity, +void gen_dffsr_complex(RTLIL::Module *mod, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, RTLIL::SigSpec clk, bool clk_polarity, std::map> &async_rules, RTLIL::Process *proc) { RTLIL::SigSpec sig_sr_set = RTLIL::SigSpec(0, sig_d.size()); @@ -140,7 +143,7 @@ static void gen_dffsr_complex(RTLIL::Module *mod, RTLIL::SigSpec sig_d, RTLIL::S cell->type.c_str(), cell->name.c_str(), clk_polarity ? "positive" : "negative"); } -static void gen_dffsr(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_out, +void gen_dffsr(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_out, bool clk_polarity, bool set_polarity, RTLIL::SigSpec clk, RTLIL::SigSpec set, RTLIL::Process *proc) { std::stringstream sstr; @@ -187,7 +190,7 @@ static void gen_dffsr(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::SigSpec clk_polarity ? "positive" : "negative", set_polarity ? "positive" : "negative"); } -static void gen_dff(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::Const val_rst, RTLIL::SigSpec sig_out, +void gen_dff(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::Const val_rst, RTLIL::SigSpec sig_out, bool clk_polarity, bool arst_polarity, RTLIL::SigSpec clk, RTLIL::SigSpec *arst, RTLIL::Process *proc) { std::stringstream sstr; @@ -215,7 +218,7 @@ static void gen_dff(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::Const val_ log(".\n"); } -static void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce) +void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce) { while (1) { @@ -380,3 +383,4 @@ struct ProcDffPass : public Pass { } } ProcDffPass; +PRIVATE_NAMESPACE_END diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc index c72840c02..dff68159f 100644 --- a/passes/proc/proc_init.cc +++ b/passes/proc/proc_init.cc @@ -23,7 +23,10 @@ #include #include -static void proc_get_const(RTLIL::SigSpec &sig, RTLIL::CaseRule &rule) +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +void proc_get_const(RTLIL::SigSpec &sig, RTLIL::CaseRule &rule) { log_assert(rule.compare.size() == 0); @@ -37,7 +40,7 @@ static void proc_get_const(RTLIL::SigSpec &sig, RTLIL::CaseRule &rule) } } -static void proc_init(RTLIL::Module *mod, RTLIL::Process *proc) +void proc_init(RTLIL::Module *mod, RTLIL::Process *proc) { bool found_init = false; @@ -109,3 +112,4 @@ struct ProcInitPass : public Pass { } } ProcInitPass; +PRIVATE_NAMESPACE_END diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc index c00b00a2a..4aa1aab54 100644 --- a/passes/proc/proc_mux.cc +++ b/passes/proc/proc_mux.cc @@ -24,7 +24,10 @@ #include #include -static RTLIL::SigSpec find_any_lvalue(const RTLIL::CaseRule *cs) +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +RTLIL::SigSpec find_any_lvalue(const RTLIL::CaseRule *cs) { for (auto &action : cs->actions) { if (action.first.size()) @@ -41,7 +44,7 @@ static RTLIL::SigSpec find_any_lvalue(const RTLIL::CaseRule *cs) return RTLIL::SigSpec(); } -static void extract_core_signal(const RTLIL::CaseRule *cs, RTLIL::SigSpec &sig) +void extract_core_signal(const RTLIL::CaseRule *cs, RTLIL::SigSpec &sig) { for (auto &action : cs->actions) { RTLIL::SigSpec lvalue = action.first.extract(sig); @@ -54,7 +57,7 @@ static void extract_core_signal(const RTLIL::CaseRule *cs, RTLIL::SigSpec &sig) extract_core_signal(cs2, sig); } -static RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SwitchRule *sw) +RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SwitchRule *sw) { std::stringstream sstr; sstr << "$procmux$" << (autoidx++); @@ -122,7 +125,7 @@ static RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, return RTLIL::SigSpec(ctrl_wire); } -static RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SigSpec when_signal, RTLIL::SigSpec else_signal, RTLIL::Cell *&last_mux_cell, RTLIL::SwitchRule *sw) +RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SigSpec when_signal, RTLIL::SigSpec else_signal, RTLIL::Cell *&last_mux_cell, RTLIL::SwitchRule *sw) { log_assert(when_signal.size() == else_signal.size()); @@ -156,7 +159,7 @@ static RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, return RTLIL::SigSpec(result_wire); } -static void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SigSpec when_signal, RTLIL::Cell *last_mux_cell, RTLIL::SwitchRule *sw) +void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector &compare, RTLIL::SigSpec when_signal, RTLIL::Cell *last_mux_cell, RTLIL::SwitchRule *sw) { log_assert(last_mux_cell != NULL); log_assert(when_signal.size() == last_mux_cell->getPort("\\A").size()); @@ -176,7 +179,7 @@ static void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const last_mux_cell->parameters["\\S_WIDTH"] = last_mux_cell->getPort("\\S").size(); } -static RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, RTLIL::CaseRule *cs, const RTLIL::SigSpec &sig, const RTLIL::SigSpec &defval) +RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, RTLIL::CaseRule *cs, const RTLIL::SigSpec &sig, const RTLIL::SigSpec &defval) { RTLIL::SigSpec result = defval; @@ -233,7 +236,7 @@ static RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, RTLIL::CaseRule *cs return result; } -static void proc_mux(RTLIL::Module *mod, RTLIL::Process *proc) +void proc_mux(RTLIL::Module *mod, RTLIL::Process *proc) { bool first = true; while (1) @@ -283,3 +286,4 @@ struct ProcMuxPass : public Pass { } } ProcMuxPass; +PRIVATE_NAMESPACE_END diff --git a/passes/proc/proc_rmdead.cc b/passes/proc/proc_rmdead.cc index fe3532da8..d701f00a5 100644 --- a/passes/proc/proc_rmdead.cc +++ b/passes/proc/proc_rmdead.cc @@ -25,7 +25,10 @@ #include #include -static void proc_rmdead(RTLIL::SwitchRule *sw, int &counter) +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +void proc_rmdead(RTLIL::SwitchRule *sw, int &counter) { BitPatternPool pool(sw->signal); @@ -98,3 +101,4 @@ struct ProcRmdeadPass : public Pass { } } ProcRmdeadPass; +PRIVATE_NAMESPACE_END diff --git a/passes/sat/eval.cc b/passes/sat/eval.cc index f07ad943c..e58a194ec 100644 --- a/passes/sat/eval.cc +++ b/passes/sat/eval.cc @@ -31,7 +31,8 @@ #include #include -namespace { +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN /* this should only be used for regression testing of ConstEval -- see vloghammer */ struct BruteForceEquivChecker @@ -357,8 +358,6 @@ struct VlogHammerReporter } }; -} /* namespace */ - struct EvalPass : public Pass { EvalPass() : Pass("eval", "evaluate the circuit given an input") { } virtual void help() @@ -601,3 +600,4 @@ struct EvalPass : public Pass { } } EvalPass; +PRIVATE_NAMESPACE_END diff --git a/passes/sat/expose.cc b/passes/sat/expose.cc index e856fdf76..46ebdb846 100644 --- a/passes/sat/expose.cc +++ b/passes/sat/expose.cc @@ -23,6 +23,9 @@ #include "kernel/rtlil.h" #include "kernel/log.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct dff_map_info_t { RTLIL::SigSpec sig_d, sig_clk, sig_arst; bool clk_polarity, arst_polarity; @@ -37,7 +40,7 @@ struct dff_map_bit_info_t { RTLIL::Cell *cell; }; -static bool consider_wire(RTLIL::Wire *wire, std::map &dff_dq_map) +bool consider_wire(RTLIL::Wire *wire, std::map &dff_dq_map) { if (wire->name[0] == '$' || dff_dq_map.count(wire->name)) return false; @@ -46,7 +49,7 @@ static bool consider_wire(RTLIL::Wire *wire, std::map &dff_cells, RTLIL::Cell *cell) +bool consider_cell(RTLIL::Design *design, std::set &dff_cells, RTLIL::Cell *cell) { if (cell->name[0] == '$' || dff_cells.count(cell->name)) return false; @@ -55,7 +58,7 @@ static bool consider_cell(RTLIL::Design *design, std::set &dff_ return true; } -static bool compare_wires(RTLIL::Wire *wire1, RTLIL::Wire *wire2) +bool compare_wires(RTLIL::Wire *wire1, RTLIL::Wire *wire2) { log_assert(wire1->name == wire2->name); if (wire1->width != wire2->width) @@ -63,7 +66,7 @@ static bool compare_wires(RTLIL::Wire *wire1, RTLIL::Wire *wire2) return true; } -static bool compare_cells(RTLIL::Cell *cell1, RTLIL::Cell *cell2) +bool compare_cells(RTLIL::Cell *cell1, RTLIL::Cell *cell2) { log_assert(cell1->name == cell2->name); if (cell1->type != cell2->type) @@ -73,7 +76,7 @@ static bool compare_cells(RTLIL::Cell *cell1, RTLIL::Cell *cell2) return true; } -static void find_dff_wires(std::set &dff_wires, RTLIL::Module *module) +void find_dff_wires(std::set &dff_wires, RTLIL::Module *module) { CellTypes ct; ct.setup_internals_mem(); @@ -93,7 +96,7 @@ static void find_dff_wires(std::set &dff_wires, RTLIL::Module * } } -static void create_dff_dq_map(std::map &map, RTLIL::Design *design, RTLIL::Module *module) +void create_dff_dq_map(std::map &map, RTLIL::Design *design, RTLIL::Module *module) { std::map bit_info; SigMap sigmap(module); @@ -208,7 +211,7 @@ static void create_dff_dq_map(std::map &map, RT } } -static RTLIL::Wire *add_new_wire(RTLIL::Module *module, RTLIL::IdString name, int width = 1) +RTLIL::Wire *add_new_wire(RTLIL::Module *module, RTLIL::IdString name, int width = 1) { if (module->count_id(name)) log_error("Attempting to create wire %s, but a wire of this name exists already! Hint: Try another value for -sep.\n", log_id(name)); @@ -644,3 +647,4 @@ struct ExposePass : public Pass { } } ExposePass; +PRIVATE_NAMESPACE_END diff --git a/passes/sat/freduce.cc b/passes/sat/freduce.cc index bfed0005d..fbca35861 100644 --- a/passes/sat/freduce.cc +++ b/passes/sat/freduce.cc @@ -28,7 +28,8 @@ #include #include -namespace { +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN bool inv_mode; int verbose_level, reduce_counter, reduce_stop_at; @@ -745,8 +746,6 @@ struct FreduceWorker } }; -} /* namespace */ - struct FreducePass : public Pass { FreducePass() : Pass("freduce", "perform functional reduction") { } virtual void help() @@ -827,3 +826,4 @@ struct FreducePass : public Pass { } } FreducePass; +PRIVATE_NAMESPACE_END diff --git a/passes/sat/miter.cc b/passes/sat/miter.cc index b3adefb92..9853cd0c6 100644 --- a/passes/sat/miter.cc +++ b/passes/sat/miter.cc @@ -21,7 +21,10 @@ #include "kernel/rtlil.h" #include "kernel/log.h" -static void create_miter_equiv(struct Pass *that, std::vector args, RTLIL::Design *design) +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +void create_miter_equiv(struct Pass *that, std::vector args, RTLIL::Design *design) { bool flag_ignore_gold_x = false; bool flag_make_outputs = false; @@ -299,3 +302,4 @@ struct MiterPass : public Pass { } } MiterPass; +PRIVATE_NAMESPACE_END diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index fd0abf4a5..f0c88e52b 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -33,7 +33,8 @@ #include #include -namespace { +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN struct SatHelper { @@ -766,9 +767,7 @@ struct SatHelper } }; -} /* namespace */ - -static void print_proof_failed() +void print_proof_failed() { log("\n"); log(" ______ ___ ___ _ _ _ _ \n"); @@ -780,7 +779,7 @@ static void print_proof_failed() log("\n"); } -static void print_timeout() +void print_timeout() { log("\n"); log(" _____ _ _ _____ ____ _ _____\n"); @@ -791,7 +790,7 @@ static void print_timeout() log("\n"); } -static void print_qed() +void print_qed() { log("\n"); log(" /$$$$$$ /$$$$$$$$ /$$$$$$$ \n"); @@ -1484,3 +1483,4 @@ struct SatPass : public Pass { } } SatPass; +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc index 1115eead5..f8a08841a 100644 --- a/passes/techmap/alumacc.cc +++ b/passes/techmap/alumacc.cc @@ -21,6 +21,9 @@ #include "kernel/sigtools.h" #include "kernel/macc.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct AlumaccWorker { RTLIL::Module *module; @@ -561,3 +564,4 @@ struct AlumaccPass : public Pass { } } AlumaccPass; +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index 07993b868..2a6813351 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -23,7 +23,8 @@ #include #include -using namespace PASS_DFFLIBMAP; +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN struct cell_mapping { std::string cell_name; @@ -538,3 +539,4 @@ struct DfflibmapPass : public Pass { } } DfflibmapPass; +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc index 221e9e49d..e0b1d360a 100644 --- a/passes/techmap/extract.cc +++ b/passes/techmap/extract.cc @@ -26,256 +26,240 @@ #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + using RTLIL::id2cstr; -namespace +class SubCircuitSolver : public SubCircuit::Solver { - class SubCircuitSolver : public SubCircuit::Solver +public: + bool ignore_parameters; + std::set> ignored_parameters; + std::set cell_attr, wire_attr; + + SubCircuitSolver() : ignore_parameters(false) { - public: - bool ignore_parameters; - std::set> ignored_parameters; - std::set cell_attr, wire_attr; + } - SubCircuitSolver() : ignore_parameters(false) - { - } - - bool compareAttributes(const std::set &attr, const std::map &needleAttr, const std::map &haystackAttr) - { - for (auto &it : attr) { - size_t nc = needleAttr.count(it), hc = haystackAttr.count(it); - if (nc != hc || (nc > 0 && needleAttr.at(it) != haystackAttr.at(it))) - return false; - } - return true; - } - - RTLIL::Const unified_param(RTLIL::IdString cell_type, RTLIL::IdString param, RTLIL::Const value) - { - if (cell_type.substr(0, 1) != "$" || cell_type.substr(0, 2) == "$_") - return value; - - #define param_bool(_n) if (param == _n) return value.as_bool(); - param_bool("\\ARST_POLARITY"); - param_bool("\\A_SIGNED"); - param_bool("\\B_SIGNED"); - param_bool("\\CLK_ENABLE"); - param_bool("\\CLK_POLARITY"); - param_bool("\\CLR_POLARITY"); - param_bool("\\EN_POLARITY"); - param_bool("\\SET_POLARITY"); - param_bool("\\TRANSPARENT"); - #undef param_bool - - #define param_int(_n) if (param == _n) return value.as_int(); - param_int("\\ABITS") - param_int("\\A_WIDTH") - param_int("\\B_WIDTH") - param_int("\\CTRL_IN_WIDTH") - param_int("\\CTRL_OUT_WIDTH") - param_int("\\OFFSET") - param_int("\\PRIORITY") - param_int("\\RD_PORTS") - param_int("\\SIZE") - param_int("\\STATE_BITS") - param_int("\\STATE_NUM") - param_int("\\STATE_NUM_LOG2") - param_int("\\STATE_RST") - param_int("\\S_WIDTH") - param_int("\\TRANS_NUM") - param_int("\\WIDTH") - param_int("\\WR_PORTS") - param_int("\\Y_WIDTH") - #undef param_int - - return value; - } - - virtual bool userCompareNodes(const std::string &, const std::string &, void *needleUserData, - const std::string &, const std::string &, void *haystackUserData, const std::map &portMapping) - { - RTLIL::Cell *needleCell = (RTLIL::Cell*) needleUserData; - RTLIL::Cell *haystackCell = (RTLIL::Cell*) haystackUserData; - - if (!needleCell || !haystackCell) { - log_assert(!needleCell && !haystackCell); - return true; - } - - if (!ignore_parameters) { - std::map needle_param, haystack_param; - for (auto &it : needleCell->parameters) - if (!ignored_parameters.count(std::pair(needleCell->type, it.first))) - needle_param[it.first] = unified_param(needleCell->type, it.first, it.second); - for (auto &it : haystackCell->parameters) - if (!ignored_parameters.count(std::pair(haystackCell->type, it.first))) - haystack_param[it.first] = unified_param(haystackCell->type, it.first, it.second); - if (needle_param != haystack_param) - return false; - } - - if (cell_attr.size() > 0 && !compareAttributes(cell_attr, needleCell->attributes, haystackCell->attributes)) + bool compareAttributes(const std::set &attr, const std::map &needleAttr, const std::map &haystackAttr) + { + for (auto &it : attr) { + size_t nc = needleAttr.count(it), hc = haystackAttr.count(it); + if (nc != hc || (nc > 0 && needleAttr.at(it) != haystackAttr.at(it))) return false; + } + return true; + } - if (wire_attr.size() > 0) - { - RTLIL::Wire *lastNeedleWire = NULL; - RTLIL::Wire *lastHaystackWire = NULL; - std::map emptyAttr; + RTLIL::Const unified_param(RTLIL::IdString cell_type, RTLIL::IdString param, RTLIL::Const value) + { + if (cell_type.substr(0, 1) != "$" || cell_type.substr(0, 2) == "$_") + return value; - for (auto &conn : needleCell->connections()) - { - RTLIL::SigSpec needleSig = conn.second; - RTLIL::SigSpec haystackSig = haystackCell->getPort(portMapping.at(conn.first.str())); + #define param_bool(_n) if (param == _n) return value.as_bool(); + param_bool("\\ARST_POLARITY"); + param_bool("\\A_SIGNED"); + param_bool("\\B_SIGNED"); + param_bool("\\CLK_ENABLE"); + param_bool("\\CLK_POLARITY"); + param_bool("\\CLR_POLARITY"); + param_bool("\\EN_POLARITY"); + param_bool("\\SET_POLARITY"); + param_bool("\\TRANSPARENT"); + #undef param_bool - for (int i = 0; i < std::min(needleSig.size(), haystackSig.size()); i++) { - RTLIL::Wire *needleWire = needleSig[i].wire, *haystackWire = haystackSig[i].wire; - if (needleWire != lastNeedleWire || haystackWire != lastHaystackWire) - if (!compareAttributes(wire_attr, needleWire ? needleWire->attributes : emptyAttr, haystackWire ? haystackWire->attributes : emptyAttr)) - return false; - lastNeedleWire = needleWire, lastHaystackWire = haystackWire; - } - } - } + #define param_int(_n) if (param == _n) return value.as_int(); + param_int("\\ABITS") + param_int("\\A_WIDTH") + param_int("\\B_WIDTH") + param_int("\\CTRL_IN_WIDTH") + param_int("\\CTRL_OUT_WIDTH") + param_int("\\OFFSET") + param_int("\\PRIORITY") + param_int("\\RD_PORTS") + param_int("\\SIZE") + param_int("\\STATE_BITS") + param_int("\\STATE_NUM") + param_int("\\STATE_NUM_LOG2") + param_int("\\STATE_RST") + param_int("\\S_WIDTH") + param_int("\\TRANS_NUM") + param_int("\\WIDTH") + param_int("\\WR_PORTS") + param_int("\\Y_WIDTH") + #undef param_int + return value; + } + + virtual bool userCompareNodes(const std::string &, const std::string &, void *needleUserData, + const std::string &, const std::string &, void *haystackUserData, const std::map &portMapping) + { + RTLIL::Cell *needleCell = (RTLIL::Cell*) needleUserData; + RTLIL::Cell *haystackCell = (RTLIL::Cell*) haystackUserData; + + if (!needleCell || !haystackCell) { + log_assert(!needleCell && !haystackCell); return true; } - }; - struct bit_ref_t { - std::string cell, port; - int bit; - }; + if (!ignore_parameters) { + std::map needle_param, haystack_param; + for (auto &it : needleCell->parameters) + if (!ignored_parameters.count(std::pair(needleCell->type, it.first))) + needle_param[it.first] = unified_param(needleCell->type, it.first, it.second); + for (auto &it : haystackCell->parameters) + if (!ignored_parameters.count(std::pair(haystackCell->type, it.first))) + haystack_param[it.first] = unified_param(haystackCell->type, it.first, it.second); + if (needle_param != haystack_param) + return false; + } - bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = NULL, - int max_fanout = -1, std::set> *split = NULL) - { - SigMap sigmap(mod); - std::map sig_bit_ref; - - if (sel && !sel->selected(mod)) { - log(" Skipping module %s as it is not selected.\n", id2cstr(mod->name)); + if (cell_attr.size() > 0 && !compareAttributes(cell_attr, needleCell->attributes, haystackCell->attributes)) return false; - } - if (mod->processes.size() > 0) { - log(" Skipping module %s as it contains unprocessed processes.\n", id2cstr(mod->name)); - return false; - } - - if (constports) { - graph.createNode("$const$0", "$const$0", NULL, true); - graph.createNode("$const$1", "$const$1", NULL, true); - graph.createNode("$const$x", "$const$x", NULL, true); - graph.createNode("$const$z", "$const$z", NULL, true); - graph.createPort("$const$0", "\\Y", 1); - graph.createPort("$const$1", "\\Y", 1); - graph.createPort("$const$x", "\\Y", 1); - graph.createPort("$const$z", "\\Y", 1); - graph.markExtern("$const$0", "\\Y", 0); - graph.markExtern("$const$1", "\\Y", 0); - graph.markExtern("$const$x", "\\Y", 0); - graph.markExtern("$const$z", "\\Y", 0); - } - - std::map, int> sig_use_count; - if (max_fanout > 0) - for (auto &cell_it : mod->cells_) - { - RTLIL::Cell *cell = cell_it.second; - if (!sel || sel->selected(mod, cell)) - for (auto &conn : cell->connections()) { - RTLIL::SigSpec conn_sig = conn.second; - sigmap.apply(conn_sig); - for (auto &bit : conn_sig) - if (bit.wire != NULL) - sig_use_count[std::pair(bit.wire, bit.offset)]++; - } - } - - // create graph nodes from cells - for (auto &cell_it : mod->cells_) + if (wire_attr.size() > 0) { - RTLIL::Cell *cell = cell_it.second; - if (sel && !sel->selected(mod, cell)) - continue; + RTLIL::Wire *lastNeedleWire = NULL; + RTLIL::Wire *lastHaystackWire = NULL; + std::map emptyAttr; - std::string type = cell->type.str(); - if (sel == NULL && type.substr(0, 2) == "\\$") - type = type.substr(1); - graph.createNode(cell->name.str(), type, (void*)cell); - - for (auto &conn : cell->connections()) + for (auto &conn : needleCell->connections()) { - graph.createPort(cell->name.str(), conn.first.str(), conn.second.size()); + RTLIL::SigSpec needleSig = conn.second; + RTLIL::SigSpec haystackSig = haystackCell->getPort(portMapping.at(conn.first.str())); - if (split && split->count(std::pair(cell->type, conn.first)) > 0) - continue; - - RTLIL::SigSpec conn_sig = conn.second; - sigmap.apply(conn_sig); - - for (int i = 0; i < conn_sig.size(); i++) - { - auto &bit = conn_sig[i]; - - if (bit.wire == NULL) { - if (constports) { - std::string node = "$const$x"; - if (bit == RTLIL::State::S0) node = "$const$0"; - if (bit == RTLIL::State::S1) node = "$const$1"; - if (bit == RTLIL::State::Sz) node = "$const$z"; - graph.createConnection(cell->name.str(), conn.first.str(), i, node, "\\Y", 0); - } else - graph.createConstant(cell->name.str(), conn.first.str(), i, int(bit.data)); - continue; - } - - if (max_fanout > 0 && sig_use_count[std::pair(bit.wire, bit.offset)] > max_fanout) - continue; - - if (sel && !sel->selected(mod, bit.wire)) - continue; - - if (sig_bit_ref.count(bit) == 0) { - bit_ref_t &bit_ref = sig_bit_ref[bit]; - bit_ref.cell = cell->name.str(); - bit_ref.port = conn.first.str(); - bit_ref.bit = i; - } - - bit_ref_t &bit_ref = sig_bit_ref[bit]; - graph.createConnection(bit_ref.cell, bit_ref.port, bit_ref.bit, cell->name.str(), conn.first.str(), i); + for (int i = 0; i < std::min(needleSig.size(), haystackSig.size()); i++) { + RTLIL::Wire *needleWire = needleSig[i].wire, *haystackWire = haystackSig[i].wire; + if (needleWire != lastNeedleWire || haystackWire != lastHaystackWire) + if (!compareAttributes(wire_attr, needleWire ? needleWire->attributes : emptyAttr, haystackWire ? haystackWire->attributes : emptyAttr)) + return false; + lastNeedleWire = needleWire, lastHaystackWire = haystackWire; } } } - // mark external signals (used in non-selected cells) + return true; + } +}; + +struct bit_ref_t { + std::string cell, port; + int bit; +}; + +bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = NULL, + int max_fanout = -1, std::set> *split = NULL) +{ + SigMap sigmap(mod); + std::map sig_bit_ref; + + if (sel && !sel->selected(mod)) { + log(" Skipping module %s as it is not selected.\n", id2cstr(mod->name)); + return false; + } + + if (mod->processes.size() > 0) { + log(" Skipping module %s as it contains unprocessed processes.\n", id2cstr(mod->name)); + return false; + } + + if (constports) { + graph.createNode("$const$0", "$const$0", NULL, true); + graph.createNode("$const$1", "$const$1", NULL, true); + graph.createNode("$const$x", "$const$x", NULL, true); + graph.createNode("$const$z", "$const$z", NULL, true); + graph.createPort("$const$0", "\\Y", 1); + graph.createPort("$const$1", "\\Y", 1); + graph.createPort("$const$x", "\\Y", 1); + graph.createPort("$const$z", "\\Y", 1); + graph.markExtern("$const$0", "\\Y", 0); + graph.markExtern("$const$1", "\\Y", 0); + graph.markExtern("$const$x", "\\Y", 0); + graph.markExtern("$const$z", "\\Y", 0); + } + + std::map, int> sig_use_count; + if (max_fanout > 0) for (auto &cell_it : mod->cells_) { RTLIL::Cell *cell = cell_it.second; - if (sel && !sel->selected(mod, cell)) - for (auto &conn : cell->connections()) - { + if (!sel || sel->selected(mod, cell)) + for (auto &conn : cell->connections()) { RTLIL::SigSpec conn_sig = conn.second; sigmap.apply(conn_sig); - for (auto &bit : conn_sig) - if (sig_bit_ref.count(bit) != 0) { - bit_ref_t &bit_ref = sig_bit_ref[bit]; - graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit); - } + if (bit.wire != NULL) + sig_use_count[std::pair(bit.wire, bit.offset)]++; } } - // mark external signals (used in module ports) - for (auto &wire_it : mod->wires_) + // create graph nodes from cells + for (auto &cell_it : mod->cells_) + { + RTLIL::Cell *cell = cell_it.second; + if (sel && !sel->selected(mod, cell)) + continue; + + std::string type = cell->type.str(); + if (sel == NULL && type.substr(0, 2) == "\\$") + type = type.substr(1); + graph.createNode(cell->name.str(), type, (void*)cell); + + for (auto &conn : cell->connections()) { - RTLIL::Wire *wire = wire_it.second; - if (wire->port_id > 0) + graph.createPort(cell->name.str(), conn.first.str(), conn.second.size()); + + if (split && split->count(std::pair(cell->type, conn.first)) > 0) + continue; + + RTLIL::SigSpec conn_sig = conn.second; + sigmap.apply(conn_sig); + + for (int i = 0; i < conn_sig.size(); i++) { - RTLIL::SigSpec conn_sig(wire); + auto &bit = conn_sig[i]; + + if (bit.wire == NULL) { + if (constports) { + std::string node = "$const$x"; + if (bit == RTLIL::State::S0) node = "$const$0"; + if (bit == RTLIL::State::S1) node = "$const$1"; + if (bit == RTLIL::State::Sz) node = "$const$z"; + graph.createConnection(cell->name.str(), conn.first.str(), i, node, "\\Y", 0); + } else + graph.createConstant(cell->name.str(), conn.first.str(), i, int(bit.data)); + continue; + } + + if (max_fanout > 0 && sig_use_count[std::pair(bit.wire, bit.offset)] > max_fanout) + continue; + + if (sel && !sel->selected(mod, bit.wire)) + continue; + + if (sig_bit_ref.count(bit) == 0) { + bit_ref_t &bit_ref = sig_bit_ref[bit]; + bit_ref.cell = cell->name.str(); + bit_ref.port = conn.first.str(); + bit_ref.bit = i; + } + + bit_ref_t &bit_ref = sig_bit_ref[bit]; + graph.createConnection(bit_ref.cell, bit_ref.port, bit_ref.bit, cell->name.str(), conn.first.str(), i); + } + } + } + + // mark external signals (used in non-selected cells) + for (auto &cell_it : mod->cells_) + { + RTLIL::Cell *cell = cell_it.second; + if (sel && !sel->selected(mod, cell)) + for (auto &conn : cell->connections()) + { + RTLIL::SigSpec conn_sig = conn.second; sigmap.apply(conn_sig); for (auto &bit : conn_sig) @@ -284,70 +268,86 @@ namespace graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit); } } - } - - // graph.print(); - return true; } - RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit::Solver::Result &match) + // mark external signals (used in module ports) + for (auto &wire_it : mod->wires_) { - SigMap sigmap(needle); - SigSet> sig2port; - - // create new cell - RTLIL::Cell *cell = haystack->addCell(stringf("$extract$%s$%d", needle->name.c_str(), autoidx++), needle->name); - - // create cell ports - for (auto &it : needle->wires_) { - RTLIL::Wire *wire = it.second; - if (wire->port_id > 0) { - for (int i = 0; i < wire->width; i++) - sig2port.insert(sigmap(RTLIL::SigSpec(wire, i)), std::pair(wire->name, i)); - cell->setPort(wire->name, RTLIL::SigSpec(RTLIL::State::Sz, wire->width)); - } - } - - // delete replaced cells and connect new ports - for (auto &it : match.mappings) + RTLIL::Wire *wire = wire_it.second; + if (wire->port_id > 0) { - auto &mapping = it.second; - RTLIL::Cell *needle_cell = (RTLIL::Cell*)mapping.needleUserData; - RTLIL::Cell *haystack_cell = (RTLIL::Cell*)mapping.haystackUserData; + RTLIL::SigSpec conn_sig(wire); + sigmap.apply(conn_sig); - if (needle_cell == NULL) - continue; + for (auto &bit : conn_sig) + if (sig_bit_ref.count(bit) != 0) { + bit_ref_t &bit_ref = sig_bit_ref[bit]; + graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit); + } + } + } - for (auto &conn : needle_cell->connections()) { - RTLIL::SigSpec sig = sigmap(conn.second); - if (mapping.portMapping.count(conn.first.str()) > 0 && sig2port.has(sigmap(sig))) { - for (int i = 0; i < sig.size(); i++) - for (auto &port : sig2port.find(sig[i])) { - RTLIL::SigSpec bitsig = haystack_cell->getPort(mapping.portMapping[conn.first.str()]).extract(i, 1); - RTLIL::SigSpec new_sig = cell->getPort(port.first); - new_sig.replace(port.second, bitsig); - cell->setPort(port.first, new_sig); - } + // graph.print(); + return true; +} + +RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit::Solver::Result &match) +{ + SigMap sigmap(needle); + SigSet> sig2port; + + // create new cell + RTLIL::Cell *cell = haystack->addCell(stringf("$extract$%s$%d", needle->name.c_str(), autoidx++), needle->name); + + // create cell ports + for (auto &it : needle->wires_) { + RTLIL::Wire *wire = it.second; + if (wire->port_id > 0) { + for (int i = 0; i < wire->width; i++) + sig2port.insert(sigmap(RTLIL::SigSpec(wire, i)), std::pair(wire->name, i)); + cell->setPort(wire->name, RTLIL::SigSpec(RTLIL::State::Sz, wire->width)); + } + } + + // delete replaced cells and connect new ports + for (auto &it : match.mappings) + { + auto &mapping = it.second; + RTLIL::Cell *needle_cell = (RTLIL::Cell*)mapping.needleUserData; + RTLIL::Cell *haystack_cell = (RTLIL::Cell*)mapping.haystackUserData; + + if (needle_cell == NULL) + continue; + + for (auto &conn : needle_cell->connections()) { + RTLIL::SigSpec sig = sigmap(conn.second); + if (mapping.portMapping.count(conn.first.str()) > 0 && sig2port.has(sigmap(sig))) { + for (int i = 0; i < sig.size(); i++) + for (auto &port : sig2port.find(sig[i])) { + RTLIL::SigSpec bitsig = haystack_cell->getPort(mapping.portMapping[conn.first.str()]).extract(i, 1); + RTLIL::SigSpec new_sig = cell->getPort(port.first); + new_sig.replace(port.second, bitsig); + cell->setPort(port.first, new_sig); } } - - haystack->remove(haystack_cell); } - return cell; + haystack->remove(haystack_cell); } - bool compareSortNeedleList(RTLIL::Module *left, RTLIL::Module *right) - { - int left_idx = 0, right_idx = 0; - if (left->attributes.count("\\extract_order") > 0) - left_idx = left->attributes.at("\\extract_order").as_int(); - if (right->attributes.count("\\extract_order") > 0) - right_idx = right->attributes.at("\\extract_order").as_int(); - if (left_idx != right_idx) - return left_idx < right_idx; - return left->name < right->name; - } + return cell; +} + +bool compareSortNeedleList(RTLIL::Module *left, RTLIL::Module *right) +{ + int left_idx = 0, right_idx = 0; + if (left->attributes.count("\\extract_order") > 0) + left_idx = left->attributes.at("\\extract_order").as_int(); + if (right->attributes.count("\\extract_order") > 0) + right_idx = right->attributes.at("\\extract_order").as_int(); + if (left_idx != right_idx) + return left_idx < right_idx; + return left->name < right->name; } struct ExtractPass : public Pass { @@ -761,3 +761,4 @@ struct ExtractPass : public Pass { } } ExtractPass; +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/hilomap.cc b/passes/techmap/hilomap.cc index 784c4cf31..f598ddc6a 100644 --- a/passes/techmap/hilomap.cc +++ b/passes/techmap/hilomap.cc @@ -21,6 +21,9 @@ #include "kernel/rtlil.h" #include "kernel/log.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + static std::string hicell_celltype, hicell_portname; static std::string locell_celltype, locell_portname; static bool singleton_mode; @@ -119,3 +122,4 @@ struct HilomapPass : public Pass { } } HilomapPass; +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc index 9cd23ce6f..76d6115ae 100644 --- a/passes/techmap/iopadmap.cc +++ b/passes/techmap/iopadmap.cc @@ -21,7 +21,10 @@ #include "kernel/rtlil.h" #include "kernel/log.h" -static void split_portname_pair(std::string &port1, std::string &port2) +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +void split_portname_pair(std::string &port1, std::string &port2) { size_t pos = port1.find_first_of(':'); if (pos != std::string::npos) { @@ -207,3 +210,4 @@ struct IopadmapPass : public Pass { } } IopadmapPass; +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc index 612fa1117..bf170d74c 100644 --- a/passes/techmap/libparse.cc +++ b/passes/techmap/libparse.cc @@ -29,7 +29,7 @@ #include "kernel/log.h" #endif -using namespace PASS_DFFLIBMAP; +using namespace Yosys; std::set LibertyAst::blacklist; std::set LibertyAst::whitelist; diff --git a/passes/techmap/libparse.h b/passes/techmap/libparse.h index 247487424..e947bd8cd 100644 --- a/passes/techmap/libparse.h +++ b/passes/techmap/libparse.h @@ -25,7 +25,7 @@ #include #include -namespace PASS_DFFLIBMAP +namespace Yosys { struct LibertyAst { diff --git a/passes/techmap/maccmap.cc b/passes/techmap/maccmap.cc index 2d625eefe..1da97072a 100644 --- a/passes/techmap/maccmap.cc +++ b/passes/techmap/maccmap.cc @@ -20,7 +20,8 @@ #include "kernel/yosys.h" #include "kernel/macc.h" -extern void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap = false); +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN struct MaccmapWorker { @@ -256,6 +257,11 @@ struct MaccmapWorker } }; +PRIVATE_NAMESPACE_END +YOSYS_NAMESPACE_BEGIN + +extern void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap = false); + void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap) { int width = SIZE(cell->getPort("\\Y")); @@ -354,6 +360,9 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap) } } +YOSYS_NAMESPACE_END +PRIVATE_NAMESPACE_BEGIN + struct MaccmapPass : public Pass { MaccmapPass() : Pass("maccmap", "mapping macc cells") { } virtual void help() @@ -392,3 +401,4 @@ struct MaccmapPass : public Pass { } } MaccmapPass; +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index f8d5d4584..1cba34336 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -24,7 +24,8 @@ #include #include -extern void simplemap_get_mappers(std::map &mappers); +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN static void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell) { @@ -372,6 +373,11 @@ static void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell) } } +PRIVATE_NAMESPACE_END +YOSYS_NAMESPACE_BEGIN + +extern void simplemap_get_mappers(std::map &mappers); + void simplemap_get_mappers(std::map &mappers) { mappers["$not"] = simplemap_not; @@ -398,6 +404,9 @@ void simplemap_get_mappers(std::map &mappers); // see maccmap.cc extern void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap = false); -static void apply_prefix(std::string prefix, std::string &id) +YOSYS_NAMESPACE_END + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +void apply_prefix(std::string prefix, std::string &id) { if (id[0] == '\\') id = prefix + "." + id.substr(1); @@ -42,7 +49,7 @@ static void apply_prefix(std::string prefix, std::string &id) id = "$techmap" + prefix + "." + id; } -static void apply_prefix(std::string prefix, RTLIL::SigSpec &sig, RTLIL::Module *module) +void apply_prefix(std::string prefix, RTLIL::SigSpec &sig, RTLIL::Module *module) { std::vector chunks = sig; for (auto &chunk : chunks) @@ -1080,3 +1087,4 @@ struct FlattenPass : public Pass { } } FlattenPass; +PRIVATE_NAMESPACE_END diff --git a/passes/tests/test_abcloop.cc b/passes/tests/test_abcloop.cc index 0a0ceb1d1..1ede137ee 100644 --- a/passes/tests/test_abcloop.cc +++ b/passes/tests/test_abcloop.cc @@ -21,6 +21,9 @@ #include "kernel/yosys.h" #include "kernel/satgen.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + static uint32_t xorshift32_state = 123456789; static uint32_t xorshift32(uint32_t limit) { @@ -283,3 +286,4 @@ struct TestAbcloopPass : public Pass { } } TestAbcloopPass; +PRIVATE_NAMESPACE_END diff --git a/passes/tests/test_autotb.cc b/passes/tests/test_autotb.cc index eed0f75f9..05caf6b21 100644 --- a/passes/tests/test_autotb.cc +++ b/passes/tests/test_autotb.cc @@ -22,6 +22,7 @@ #include #include +USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN static std::string id(std::string internal_id) diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index 1fa90b540..d611d56c3 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -24,6 +24,9 @@ #include "kernel/macc.h" #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + static uint32_t xorshift32_state = 123456789; static uint32_t xorshift32(uint32_t limit) { @@ -743,3 +746,4 @@ struct TestCellPass : public Pass { } } TestCellPass; +PRIVATE_NAMESPACE_END diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 4ccacd30b..8b41a003d 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -22,7 +22,10 @@ #include "kernel/rtlil.h" #include "kernel/log.h" -static bool check_label(bool &active, std::string run_from, std::string run_to, std::string label) +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +bool check_label(bool &active, std::string run_from, std::string run_to, std::string label) { if (!run_from.empty() && run_from == run_to) { active = (label == run_from); @@ -154,3 +157,4 @@ struct SynthPass : public Pass { } } SynthPass; +PRIVATE_NAMESPACE_END diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index ff906db8f..8df5c4e42 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -22,7 +22,10 @@ #include "kernel/rtlil.h" #include "kernel/log.h" -static bool check_label(bool &active, std::string run_from, std::string run_to, std::string label) +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +bool check_label(bool &active, std::string run_from, std::string run_to, std::string label) { if (label == run_from) active = true; @@ -208,3 +211,4 @@ struct SynthXilinxPass : public Pass { } } SynthXilinxPass; +PRIVATE_NAMESPACE_END From 0b8cfbc6fde8e7500c5df38c74e1da2d74e588bd Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Sep 2014 12:51:54 +0200 Subject: [PATCH 002/492] Added support for "keep" on modules --- README | 2 ++ kernel/rtlil.h | 5 +++++ passes/opt/opt_clean.cc | 2 +- passes/opt/opt_share.cc | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/README b/README index d7f5aaa4b..32a47cbfe 100644 --- a/README +++ b/README @@ -273,6 +273,8 @@ Verilog Attributes and non-standard features - The "keep" attribute on cells and wires is used to mark objects that should never be removed by the optimizer. This is used for example for cells that have hidden connections that are not part of the netlist, such as IO pads. + Setting the "keep" attribute on a module has the same effect as setting it + on all instances of the module. - The "init" attribute on wires is set by the frontend when a register is initialized "FPGA-style" with 'reg foo = val'. It can be used during synthesis diff --git a/kernel/rtlil.h b/kernel/rtlil.h index a0ae8f082..8df0bfe19 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -857,6 +857,11 @@ public: void check(); void fixup_parameters(bool set_a_signed = false, bool set_b_signed = false); + bool has_keep_attr() const { + return get_bool_attribute("\\keep") || (module && module->design && module->design->module(type) && + module->design->module(type)->get_bool_attribute("\\keep")); + } + template void rewrite_sigspecs(T functor); }; diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index d589518aa..0e5ed238f 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -48,7 +48,7 @@ void rmunused_module_cells(RTLIL::Module *module, bool verbose) wire2driver.insert(sig, cell); } } - if (cell->type == "$memwr" || cell->type == "$assert" || cell->get_bool_attribute("\\keep")) + if (cell->type == "$memwr" || cell->type == "$assert" || cell->has_keep_attr()) queue.insert(cell); unused.insert(cell); } diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index 33115349c..f8bc02205 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -196,7 +196,7 @@ struct OptShareWorker if (!ct.cell_known(cell1->type)) return cell1 < cell2; - if (cell1->get_bool_attribute("\\keep") || cell2->get_bool_attribute("\\keep")) + if (cell1->has_keep_attr() || cell2->has_keep_attr()) return cell1 < cell2; bool lt; From 2ee03f5da42e03cc2e5e17b8394ed4f0d24cf21b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Sep 2014 19:16:40 +0200 Subject: [PATCH 003/492] set "keep" on modules with $assert cells in "hierarchy" --- passes/hierarchy/hierarchy.cc | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 2c77a892a..960fc1929 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -286,6 +286,17 @@ void hierarchy(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib, bool f log("Removed %zd unused modules.\n", del_modules.size()); } +bool set_keep_assert(std::map &cache, RTLIL::Module *mod) +{ + if (cache.count(mod) == 0) + for (auto c : mod->cells()) { + RTLIL::Module *m = mod->design->module(c->type); + if ((m != nullptr && set_keep_assert(cache, m)) || c->type == "$assert") + return cache[mod] = true; + } + return cache[mod]; +} + struct HierarchyPass : public Pass { HierarchyPass() : Pass("hierarchy", "check, expand and clean up design hierarchy") { } virtual void help() @@ -317,6 +328,11 @@ struct HierarchyPass : public Pass { log(" per default this pass also converts positional arguments in cells\n"); log(" to arguments using port names. this option disables this behavior.\n"); log("\n"); + log(" -nokeep_asserts\n"); + log(" per default this pass sets the \"keep\" attribute on all modules\n"); + log(" that directly or indirectly contain one or more $assert cells. this\n"); + log(" option disables this behavior.\n"); + log("\n"); log(" -top \n"); log(" use the specified top module to built a design hierarchy. modules\n"); log(" outside this tree (unused modules) are removed.\n"); @@ -353,6 +369,7 @@ struct HierarchyPass : public Pass { bool generate_mode = false; bool keep_positionals = false; + bool nokeep_asserts = false; std::vector generate_cells; std::vector generate_ports; @@ -410,6 +427,10 @@ struct HierarchyPass : public Pass { keep_positionals = true; continue; } + if (args[argidx] == "-nokeep_asserts") { + nokeep_asserts = true; + continue; + } if (args[argidx] == "-libdir" && argidx+1 < args.size()) { libdirs.push_back(args[++argidx]); continue; @@ -477,6 +498,15 @@ struct HierarchyPass : public Pass { mod_it.second->attributes.erase("\\top"); } + if (!nokeep_asserts) { + std::map cache; + for (auto mod : design->modules()) + if (set_keep_assert(cache, mod)) { + log("Module %s directly or indirectly contains $assert cells -> setting \"keep\" attribute.\n", log_id(mod)); + mod->set_bool_attribute("\\keep"); + } + } + if (!keep_positionals) { std::set pos_mods; From 7019bc00e4ebd3c535ff6070bec4af6b7f73336b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 Oct 2014 09:55:50 +0200 Subject: [PATCH 004/492] resource sharing of $alu cells --- passes/opt/share.cc | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/passes/opt/share.cc b/passes/opt/share.cc index 03f6527c0..aae1c4f9f 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -32,7 +32,7 @@ struct ShareWorkerConfig bool opt_force; bool opt_aggressive; bool opt_fast; - std::set generic_uni_ops, generic_bin_ops, generic_cbin_ops; + std::set generic_uni_ops, generic_bin_ops, generic_cbin_ops, generic_other_ops; }; struct ShareWorker @@ -184,7 +184,7 @@ struct ShareWorker return true; } - if (config.generic_bin_ops.count(c1->type)) + if (config.generic_bin_ops.count(c1->type) || c1->type == "$alu") { if (!config.opt_aggressive) { @@ -307,7 +307,7 @@ struct ShareWorker return supercell; } - if (config.generic_bin_ops.count(c1->type) || config.generic_cbin_ops.count(c1->type)) + if (config.generic_bin_ops.count(c1->type) || config.generic_cbin_ops.count(c1->type) || c1->type == "$alu") { bool modified_src_cells = false; @@ -410,6 +410,8 @@ struct ShareWorker supercell_aux.insert(module->addMux(NEW_ID, b2, b1, act, b)); RTLIL::Wire *y = module->addWire(NEW_ID, y_width); + RTLIL::Wire *x = c1->type == "$alu" ? module->addWire(NEW_ID, y_width) : nullptr; + RTLIL::Wire *co = c1->type == "$alu" ? module->addWire(NEW_ID, y_width) : nullptr; RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type); supercell->parameters["\\A_SIGNED"] = a_signed; @@ -420,10 +422,22 @@ struct ShareWorker supercell->setPort("\\A", a); supercell->setPort("\\B", b); supercell->setPort("\\Y", y); + if (c1->type == "$alu") { + supercell->setPort("\\CI", module->Mux(NEW_ID, c2->getPort("\\CI"), c1->getPort("\\CI"), act)); + supercell->setPort("\\BI", module->Mux(NEW_ID, c2->getPort("\\BI"), c1->getPort("\\BI"), act)); + supercell->setPort("\\CO", co); + supercell->setPort("\\X", x); + } supercell->check(); supercell_aux.insert(module->addPos(NEW_ID, y, y1)); supercell_aux.insert(module->addPos(NEW_ID, y, y2)); + if (c1->type == "$alu") { + supercell_aux.insert(module->addPos(NEW_ID, co, c1->getPort("\\CO"))); + supercell_aux.insert(module->addPos(NEW_ID, co, c2->getPort("\\CO"))); + supercell_aux.insert(module->addPos(NEW_ID, x, c1->getPort("\\X"))); + supercell_aux.insert(module->addPos(NEW_ID, x, c2->getPort("\\X"))); + } supercell_aux.insert(supercell); return supercell; @@ -784,6 +798,7 @@ struct ShareWorker generic_ops.insert(config.generic_uni_ops.begin(), config.generic_uni_ops.end()); generic_ops.insert(config.generic_bin_ops.begin(), config.generic_bin_ops.end()); generic_ops.insert(config.generic_cbin_ops.begin(), config.generic_cbin_ops.end()); + generic_ops.insert(config.generic_other_ops.begin(), config.generic_other_ops.end()); fwd_ct.setup_internals(); @@ -1138,6 +1153,9 @@ struct SharePass : public Pass { config.generic_cbin_ops.insert("$logic_and"); config.generic_cbin_ops.insert("$logic_or"); + config.generic_other_ops.insert("$alu"); + // config.generic_other_ops.insert("$macc"); + log_header("Executing SHARE pass (SAT-based resource sharing).\n"); size_t argidx; From 600c6cb013b6cf872f3b3f01c7d88df2092e84d9 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 Oct 2014 10:04:15 +0200 Subject: [PATCH 005/492] remove buffers in opt_clean --- passes/opt/opt_clean.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 0e5ed238f..15bbf54e0 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -293,6 +293,19 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose) if (verbose) log("Finding unused cells or wires in module %s..\n", module->name.c_str()); + std::vector delcells; + for (auto cell : module->cells()) + if (cell->type == "$pos") { + bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); + RTLIL::SigSpec a = cell->getPort("\\A"); + RTLIL::SigSpec y = cell->getPort("\\Y"); + a.extend_u0(SIZE(y), is_signed); + module->connect(y, a); + delcells.push_back(cell); + } + for (auto cell : delcells) + module->remove(cell); + rmunused_module_cells(module, verbose); rmunused_module_signals(module, purge_mode, verbose); } From c3e779a65f285afa123b990f3a717a7ae8e028f5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 Oct 2014 10:12:28 +0200 Subject: [PATCH 006/492] Added $_BUF_ cell type --- kernel/celltypes.h | 3 +++ kernel/rtlil.cc | 1 + passes/abc/abc.cc | 10 +++++++--- passes/opt/opt_clean.cc | 4 ++-- techlibs/common/simcells.v | 6 ++++++ 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 85c21ef3c..2774073dc 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -130,6 +130,7 @@ struct CellTypes void setup_stdcells() { + setup_type("$_BUF_", {"\\A"}, {"\\Y"}, true); setup_type("$_NOT_", {"\\A"}, {"\\Y"}, true); setup_type("$_AND_", {"\\A", "\\B"}, {"\\Y"}, true); setup_type("$_NAND_", {"\\A", "\\B"}, {"\\Y"}, true); @@ -261,6 +262,8 @@ struct CellTypes HANDLE_CELL_TYPE(neg) #undef HANDLE_CELL_TYPE + if (type == "$_BUF_") + return arg1; if (type == "$_NOT_") return eval_not(arg1); if (type == "$_AND_") diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 00be796f8..89132ea29 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -870,6 +870,7 @@ namespace { return; } + if (cell->type == "$_BUF_") { check_gate("AY"); return; } if (cell->type == "$_NOT_") { check_gate("AY"); return; } if (cell->type == "$_AND_") { check_gate("ABY"); return; } if (cell->type == "$_NAND_") { check_gate("ABY"); return; } diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 1a7de0663..3e1054118 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -59,6 +59,7 @@ PRIVATE_NAMESPACE_BEGIN enum class gate_type_t { G_NONE, G_FF, + G_BUF, G_NOT, G_AND, G_NAND, @@ -160,7 +161,7 @@ static void extract_cell(RTLIL::Cell *cell, bool keepff) return; } - if (cell->type == "$_NOT_") + if (cell->type.in("$_BUF_", "$_NOT_")) { RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_y = cell->getPort("\\Y"); @@ -168,7 +169,7 @@ static void extract_cell(RTLIL::Cell *cell, bool keepff) assign_map.apply(sig_a); assign_map.apply(sig_y); - map_signal(sig_y, G(NOT), map_signal(sig_a)); + map_signal(sig_y, cell->type == "$_BUF_" ? G(BUF) : G(NOT), map_signal(sig_a)); module->remove(cell); return; @@ -645,7 +646,10 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std int count_gates = 0; for (auto &si : signal_list) { - if (si.type == G(NOT)) { + if (si.type == G(BUF)) { + fprintf(f, ".names n%d n%d\n", si.in1, si.id); + fprintf(f, "1 1\n"); + } else if (si.type == G(NOT)) { fprintf(f, ".names n%d n%d\n", si.in1, si.id); fprintf(f, "0 1\n"); } else if (si.type == G(AND)) { diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 15bbf54e0..004a2078a 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -295,8 +295,8 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose) std::vector delcells; for (auto cell : module->cells()) - if (cell->type == "$pos") { - bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); + if (cell->type.in("$pos", "$_BUF_")) { + bool is_signed = cell->type == "$pos" && cell->getParam("\\A_SIGNED").as_bool(); RTLIL::SigSpec a = cell->getPort("\\A"); RTLIL::SigSpec y = cell->getPort("\\Y"); a.extend_u0(SIZE(y), is_signed); diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v index a2a377350..88566411a 100644 --- a/techlibs/common/simcells.v +++ b/techlibs/common/simcells.v @@ -25,6 +25,12 @@ * */ +module \$_BUF_ (A, Y); +input A; +output Y; +assign Y = A; +endmodule + module \$_NOT_ (A, Y); input A; output Y; From 3e4b0cac8dc1f443bbd43030f1ce151b41555d97 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 Oct 2014 12:58:40 +0200 Subject: [PATCH 007/492] added resource sharing of $macc cells --- kernel/macc.h | 9 ++ passes/opt/share.cc | 264 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 270 insertions(+), 3 deletions(-) diff --git a/kernel/macc.h b/kernel/macc.h index 271141112..7d70a2686 100644 --- a/kernel/macc.h +++ b/kernel/macc.h @@ -45,6 +45,9 @@ struct Macc if (SIZE(port.in_a) == 0 && SIZE(port.in_b) == 0) continue; + if (SIZE(port.in_a) < SIZE(port.in_b)) + std::swap(port.in_a, port.in_b); + if (SIZE(port.in_a) == 1 && SIZE(port.in_b) == 0 && !port.is_signed && !port.do_subtract) { bit_ports.append(port.in_a); continue; @@ -224,6 +227,12 @@ struct Macc return true; } + + Macc(RTLIL::Cell *cell = nullptr) + { + if (cell != nullptr) + from_cell(cell); + } }; YOSYS_NAMESPACE_END diff --git a/passes/opt/share.cc b/passes/opt/share.cc index aae1c4f9f..ffcd8c833 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -22,6 +22,7 @@ #include "kernel/sigtools.h" #include "kernel/modtools.h" #include "kernel/utils.h" +#include "kernel/macc.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -100,6 +101,243 @@ struct ShareWorker } + // --------------------------------------------------- + // Code for sharing and comparing MACC cells + // --------------------------------------------------- + + static int bits_macc_port(const Macc::port_t &p, int width) + { + if (SIZE(p.in_a) == 0 || SIZE(p.in_b) == 0) + return std::min(std::max(SIZE(p.in_a), SIZE(p.in_b)), width); + return std::min(SIZE(p.in_a), width) * std::min(SIZE(p.in_b), width) / 2; + } + + static int bits_macc(const Macc &m, int width) + { + int bits = SIZE(m.bit_ports); + for (auto &p : m.ports) + bits += bits_macc_port(p, width); + return bits; + } + + static int bits_macc(RTLIL::Cell *c) + { + Macc m(c); + int width = SIZE(c->getPort("\\Y")); + return bits_macc(m, width); + } + + static bool cmp_macc_ports(const Macc::port_t &p1, const Macc::port_t &p2) + { + bool mul1 = SIZE(p1.in_a) && SIZE(p1.in_b); + bool mul2 = SIZE(p2.in_a) && SIZE(p2.in_b); + + int w1 = mul1 ? SIZE(p1.in_a) * SIZE(p1.in_b) : SIZE(p1.in_a) + SIZE(p1.in_b); + int w2 = mul2 ? SIZE(p2.in_a) * SIZE(p2.in_b) : SIZE(p2.in_a) + SIZE(p2.in_b); + + if (mul1 != mul2) + return mul1; + + if (w1 != w2) + return w1 > w2; + + if (p1.is_signed != p2.is_signed) + return p1.is_signed < p2.is_signed; + + if (p1.do_subtract != p2.do_subtract) + return p1.do_subtract < p2.do_subtract; + + if (p1.in_a != p2.in_a) + return p1.in_a < p2.in_a; + + if (p1.in_b != p2.in_b) + return p1.in_b < p2.in_b; + + return false; + } + + int share_macc_ports(Macc::port_t &p1, Macc::port_t &p2, int w1, int w2, + RTLIL::SigSpec act = RTLIL::SigSpec(), Macc *supermacc = nullptr, std::set *supercell_aux = nullptr) + { + if (p1.do_subtract != p2.do_subtract) + return -1; + + bool mul1 = SIZE(p1.in_a) && SIZE(p1.in_b); + bool mul2 = SIZE(p2.in_a) && SIZE(p2.in_b); + + if (mul1 != mul2) + return -1; + + bool force_signed = false, force_not_signed = false; + + if ((SIZE(p1.in_a) && SIZE(p1.in_a) < w1) || (SIZE(p1.in_b) && SIZE(p1.in_b) < w1)) { + if (p1.is_signed) + force_signed = true; + else + force_not_signed = true; + } + + if ((SIZE(p2.in_a) && SIZE(p2.in_a) < w2) || (SIZE(p2.in_b) && SIZE(p2.in_b) < w2)) { + if (p2.is_signed) + force_signed = true; + else + force_not_signed = true; + } + + if (force_signed && force_not_signed) + return -1; + + if (supermacc) + { + RTLIL::SigSpec sig_a1 = p1.in_a, sig_b1 = p1.in_b; + RTLIL::SigSpec sig_a2 = p2.in_a, sig_b2 = p2.in_b; + + RTLIL::SigSpec sig_a = SIZE(sig_a1) > SIZE(sig_a2) ? sig_a1 : sig_a2; + RTLIL::SigSpec sig_b = SIZE(sig_b1) > SIZE(sig_b2) ? sig_b1 : sig_b2; + + sig_a1.extend_u0(SIZE(sig_a), p1.is_signed); + sig_b1.extend_u0(SIZE(sig_b), p1.is_signed); + + sig_a2.extend_u0(SIZE(sig_a), p2.is_signed); + sig_b2.extend_u0(SIZE(sig_b), p2.is_signed); + + if (supercell_aux && SIZE(sig_a)) { + sig_a = module->addWire(NEW_ID, SIZE(sig_a)); + supercell_aux->insert(module->addMux(NEW_ID, sig_a2, sig_a1, act, sig_a)); + } + + if (supercell_aux && SIZE(sig_b)) { + sig_b = module->addWire(NEW_ID, SIZE(sig_b)); + supercell_aux->insert(module->addMux(NEW_ID, sig_b2, sig_b1, act, sig_b)); + } + + Macc::port_t p; + p.in_a = sig_a; + p.in_b = sig_b; + p.is_signed = force_signed; + p.do_subtract = p1.do_subtract; + supermacc->ports.push_back(p); + } + + int score = 1000 + abs(SIZE(p1.in_a) - SIZE(p2.in_a)) * std::max(abs(SIZE(p1.in_b) - SIZE(p2.in_b)), 1); + + for (int i = 0; i < std::min(SIZE(p1.in_a), SIZE(p2.in_a)); i++) + if (p1.in_a[i] == p2.in_a[i] && score > 0) + score--; + + for (int i = 0; i < std::min(SIZE(p1.in_b), SIZE(p2.in_b)); i++) + if (p1.in_b[i] == p2.in_b[i] && score > 0) + score--; + + return score; + } + + int share_macc(RTLIL::Cell *c1, RTLIL::Cell *c2, + RTLIL::SigSpec act = RTLIL::SigSpec(), RTLIL::Cell *supercell = nullptr, std::set *supercell_aux = nullptr) + { + Macc m1(c1), m2(c2), supermacc; + + int w1 = SIZE(c1->getPort("\\Y")), w2 = SIZE(c2->getPort("\\Y")); + int width = std::max(w1, w2); + + m1.optimize(w1); + m2.optimize(w2); + + std::sort(m1.ports.begin(), m1.ports.end(), cmp_macc_ports); + std::sort(m2.ports.begin(), m2.ports.end(), cmp_macc_ports); + + std::set m1_unmapped, m2_unmapped; + + for (int i = 0; i < SIZE(m1.ports); i++) + m1_unmapped.insert(i); + + for (int i = 0; i < SIZE(m2.ports); i++) + m2_unmapped.insert(i); + + while (1) + { + int best_i = -1, best_j = -1, best_score = 0; + + for (int i : m1_unmapped) + for (int j : m2_unmapped) { + int score = share_macc_ports(m1.ports[i], m2.ports[j], w1, w2); + log("[%s, %s] vs [%s, %s] -> %d\n", log_signal(m1.ports[i].in_a), log_signal(m1.ports[i].in_b), log_signal(m2.ports[j].in_a), log_signal(m2.ports[j].in_b), score); + if (score >= 0 && (best_i < 0 || best_score > score)) + best_i = i, best_j = j, best_score = score; + } + + if (best_i >= 0) { + m1_unmapped.erase(best_i); + m2_unmapped.erase(best_j); + share_macc_ports(m1.ports[best_i], m2.ports[best_j], w1, w2, act, &supermacc, supercell_aux); + } else + break; + } + + for (int i : m1_unmapped) + { + RTLIL::SigSpec sig_a = m1.ports[i].in_a; + RTLIL::SigSpec sig_b = m1.ports[i].in_b; + + if (supercell_aux && SIZE(sig_a)) { + sig_a = module->addWire(NEW_ID, SIZE(sig_a)); + supercell_aux->insert(module->addMux(NEW_ID, RTLIL::SigSpec(0, SIZE(sig_a)), m1.ports[i].in_a, act, sig_a)); + } + + if (supercell_aux && SIZE(sig_b)) { + sig_b = module->addWire(NEW_ID, SIZE(sig_b)); + supercell_aux->insert(module->addMux(NEW_ID, RTLIL::SigSpec(0, SIZE(sig_b)), m1.ports[i].in_b, act, sig_b)); + } + + Macc::port_t p; + p.in_a = sig_a; + p.in_b = sig_b; + p.is_signed = m1.ports[i].is_signed; + p.do_subtract = m1.ports[i].do_subtract; + supermacc.ports.push_back(p); + } + + for (int i : m2_unmapped) + { + RTLIL::SigSpec sig_a = m2.ports[i].in_a; + RTLIL::SigSpec sig_b = m2.ports[i].in_b; + + if (supercell_aux && SIZE(sig_a)) { + sig_a = module->addWire(NEW_ID, SIZE(sig_a)); + supercell_aux->insert(module->addMux(NEW_ID, m2.ports[i].in_a, RTLIL::SigSpec(0, SIZE(sig_a)), act, sig_a)); + } + + if (supercell_aux && SIZE(sig_b)) { + sig_b = module->addWire(NEW_ID, SIZE(sig_b)); + supercell_aux->insert(module->addMux(NEW_ID, m2.ports[i].in_b, RTLIL::SigSpec(0, SIZE(sig_b)), act, sig_b)); + } + + Macc::port_t p; + p.in_a = sig_a; + p.in_b = sig_b; + p.is_signed = m2.ports[i].is_signed; + p.do_subtract = m2.ports[i].do_subtract; + supermacc.ports.push_back(p); + } + + if (supercell) + { + RTLIL::SigSpec sig_y = module->addWire(NEW_ID, width); + + supercell_aux->insert(module->addPos(NEW_ID, sig_y, c1->getPort("\\Y"))); + supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort("\\Y"))); + + supercell->setParam("\\Y_WIDTH", width); + supercell->setPort("\\Y", sig_y); + + supermacc.optimize(width); + supermacc.to_cell(supercell); + } + + return bits_macc(supermacc, width); + } + + // --------------------------------------------------- // Find shareable cells and compatible groups of cells // --------------------------------------------------- @@ -230,6 +468,14 @@ struct ShareWorker return true; } + if (c1->type == "$macc") + { + if (!config.opt_aggressive) + if (share_macc(c1, c2) > 2 * std::min(bits_macc(c1), bits_macc(c2))) return false; + + return true; + } + for (auto &it : c1->parameters) if (c2->parameters.count(it.first) == 0 || c2->parameters.at(it.first) != it.second) return false; @@ -423,8 +669,11 @@ struct ShareWorker supercell->setPort("\\B", b); supercell->setPort("\\Y", y); if (c1->type == "$alu") { - supercell->setPort("\\CI", module->Mux(NEW_ID, c2->getPort("\\CI"), c1->getPort("\\CI"), act)); - supercell->setPort("\\BI", module->Mux(NEW_ID, c2->getPort("\\BI"), c1->getPort("\\BI"), act)); + RTLIL::Wire *ci = module->addWire(NEW_ID), *bi = module->addWire(NEW_ID); + supercell_aux.insert(module->addMux(NEW_ID, c2->getPort("\\CI"), c1->getPort("\\CI"), act, ci)); + supercell_aux.insert(module->addMux(NEW_ID, c2->getPort("\\BI"), c1->getPort("\\BI"), act, bi)); + supercell->setPort("\\CI", ci); + supercell->setPort("\\BI", bi); supercell->setPort("\\CO", co); supercell->setPort("\\X", x); } @@ -443,6 +692,15 @@ struct ShareWorker return supercell; } + if (c1->type == "$macc") + { + RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type); + supercell_aux.insert(supercell); + share_macc(c1, c2, act, supercell, &supercell_aux); + supercell->check(); + return supercell; + } + if (c1->type == "$memrd") { RTLIL::Cell *supercell = module->addCell(NEW_ID, c1); @@ -1154,7 +1412,7 @@ struct SharePass : public Pass { config.generic_cbin_ops.insert("$logic_or"); config.generic_other_ops.insert("$alu"); - // config.generic_other_ops.insert("$macc"); + config.generic_other_ops.insert("$macc"); log_header("Executing SHARE pass (SAT-based resource sharing).\n"); From 56c1d4340842cd0029778a986cd1eed29c146192 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 Oct 2014 18:51:50 +0200 Subject: [PATCH 008/492] satgen import sigbit api --- kernel/satgen.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/kernel/satgen.h b/kernel/satgen.h index 84a47c43f..d4933050f 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -38,6 +38,7 @@ struct SatGen std::string prefix; SigPool initial_state; std::map asserts_a, asserts_en; + std::map> imported_signals; bool ignore_div_by_zero; bool model_undef; @@ -52,7 +53,7 @@ struct SatGen this->prefix = prefix; } - std::vector importSigSpecWorker(RTLIL::SigSpec &sig, std::string &pf, bool undef_mode, bool dup_undef) + std::vector importSigSpecWorker(RTLIL::SigSpec sig, std::string &pf, bool undef_mode, bool dup_undef) { log_assert(!undef_mode || model_undef); sigmap->apply(sig); @@ -69,6 +70,7 @@ struct SatGen } else { std::string name = pf + stringf(bit.wire->width == 1 ? "%s" : "%s [%d]", RTLIL::id2cstr(bit.wire->name), bit.offset); vec.push_back(ez->frozen_literal(name)); + imported_signals[pf][bit] = vec.back(); } return vec; } @@ -94,6 +96,20 @@ struct SatGen return importSigSpecWorker(sig, pf, true, false); } + int importSigBit(RTLIL::SigBit bit, int timestep = -1) + { + log_assert(timestep != 0); + std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep)); + return importSigSpecWorker(bit, pf, false, false).front(); + } + + bool importedSigBit(RTLIL::SigBit bit, int timestep = -1) + { + log_assert(timestep != 0); + std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep)); + return imported_signals[pf].count(bit); + } + void getAsserts(RTLIL::SigSpec &sig_a, RTLIL::SigSpec &sig_en, int timestep = -1) { std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep)); From c5c7066ea64d50a6bb24270da1579f88d26af9ec Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 Oct 2014 19:01:24 +0200 Subject: [PATCH 009/492] sat encoding for exclusive $pmux ctrl inputs in "share" pass --- passes/opt/share.cc | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/passes/opt/share.cc b/passes/opt/share.cc index ffcd8c833..44374482f 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -55,6 +55,8 @@ struct ShareWorker std::map> topo_cell_drivers; std::map> topo_bit_drivers; + std::vector> exclusive_ctrls; + // ------------------------------------------------------------------------------ // Find terminal bits -- i.e. bits that do not (exclusively) feed into a mux tree @@ -261,7 +263,6 @@ struct ShareWorker for (int i : m1_unmapped) for (int j : m2_unmapped) { int score = share_macc_ports(m1.ports[i], m2.ports[j], w1, w2); - log("[%s, %s] vs [%s, %s] -> %d\n", log_signal(m1.ports[i].in_a), log_signal(m1.ports[i].in_b), log_signal(m2.ports[j].in_a), log_signal(m2.ports[j].in_b), score); if (score >= 0 && (best_i < 0 || best_score > score)) best_i = i, best_j = j, best_score = score; } @@ -346,10 +347,8 @@ struct ShareWorker void find_shareable_cells() { - for (auto &it : module->cells_) + for (auto cell : module->cells()) { - RTLIL::Cell *cell = it.second; - if (!design->selected(module, cell) || !modwalker.ct.cell_known(cell->type)) continue; @@ -1081,6 +1080,13 @@ struct ShareWorker log("Found %d cells in module %s that may be considered for resource sharing.\n", SIZE(shareable_cells), log_id(module)); + for (auto cell : module->cells()) + if (cell->type == "$pmux") + for (auto bit : cell->getPort("\\S")) + for (auto other_bit : cell->getPort("\\S")) + if (bit < other_bit) + exclusive_ctrls.push_back(std::pair(bit, other_bit)); + while (!shareable_cells.empty() && config.limit != 0) { RTLIL::Cell *cell = *shareable_cells.begin(); @@ -1206,6 +1212,12 @@ struct ShareWorker break; } + for (auto it : exclusive_ctrls) + if (satgen.importedSigBit(it.first) && satgen.importedSigBit(it.second)) { + log(" Adding exclusive control bits: %s vs. %s\n", log_signal(it.first), log_signal(it.second)); + ez.assume(ez.NOT(ez.AND(satgen.importSigBit(it.first), satgen.importSigBit(it.second)))); + } + if (!ez.solve(ez.expression(ez.OpOr, cell_active))) { log(" According to the SAT solver the cell %s is never active. Sharing is pointless, we simply remove it.\n", log_id(cell)); cells_to_remove.insert(cell); From 9dea161321c7a3fb47b5e085f91b4ecf40c9e209 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 Oct 2014 19:21:04 +0200 Subject: [PATCH 010/492] sort cell types in "stat" output by name --- passes/cmds/stat.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index b21ba01ba..51f1f0ca1 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -33,7 +33,7 @@ struct statdata_t STAT_INT_MEMBERS #undef X - std::map num_cells_by_type; + std::map num_cells_by_type; statdata_t operator+(const statdata_t &other) const { @@ -147,7 +147,7 @@ struct statdata_t statdata_t hierarchy_worker(std::map &mod_stat, RTLIL::IdString mod, int level) { statdata_t mod_data = mod_stat.at(mod); - std::map num_cells_by_type; + std::map num_cells_by_type; num_cells_by_type.swap(mod_data.num_cells_by_type); for (auto &it : num_cells_by_type) From 696d7ed40ed9de48629e31a0c1cb7f1f586306e9 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 8 Oct 2014 21:38:37 +0200 Subject: [PATCH 011/492] Fixes in "hilomap" help message --- passes/techmap/hilomap.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/passes/techmap/hilomap.cc b/passes/techmap/hilomap.cc index f598ddc6a..9a14ffa3c 100644 --- a/passes/techmap/hilomap.cc +++ b/passes/techmap/hilomap.cc @@ -60,9 +60,7 @@ struct HilomapPass : public Pass { log("\n"); log(" hilomap [options] [selection]\n"); log("\n"); - log("Map module inputs/outputs to PAD cells from a library. This pass\n"); - log("can only map to very simple PAD cells. Use 'techmap' to further map\n"); - log("the resulting cells to more sophisticated PAD cells.\n"); + log("Map constants to 'tielo' and 'tiehi' driver cells.\n"); log("\n"); log(" -hicell \n"); log(" Replace constant hi bits with this cell.\n"); @@ -78,7 +76,7 @@ struct HilomapPass : public Pass { } virtual void execute(std::vector args, RTLIL::Design *design) { - log_header("Executing HILOPAD pass (mapping to constant drivers).\n"); + log_header("Executing HILOMAP pass (mapping to constant drivers).\n"); hicell_celltype = std::string(); hicell_portname = std::string(); From ccf7b2e342cd4212ca2c2c94735a3f916b7d790f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 9 Oct 2014 10:50:44 +0200 Subject: [PATCH 012/492] Added mxe-based cross build for win32 --- Makefile | 24 +++++++++++++++++++++--- passes/techmap/Makefile.inc | 6 +++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 00979c464..6faeeb4ce 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ CONFIG := clang # CONFIG := gcc # CONFIG := gcc-4.6 # CONFIG := emcc +# CONFIG := mxe # features (the more the better) ENABLE_TCL := 1 @@ -17,10 +18,11 @@ ENABLE_GPROF := 0 DESTDIR := /usr/local INSTALL_SUDO := +EXE = OBJS = GENFILES = EXTRA_TARGETS = -TARGETS = yosys yosys-config +TARGETS = yosys$(EXE) yosys-config PRETTY = 1 SMALL = 0 @@ -83,6 +85,15 @@ else ifeq ($(CONFIG),emcc) CXX = emcc CXXFLAGS += -std=c++11 -Os -Wno-warn-absolute-paths CXXFLAGS := $(filter-out -ggdb,$(CXXFLAGS)) +EXE = .html + +else ifeq ($(CONFIG),mxe) +CXX = /usr/local/src/mxe/usr/bin/i686-pc-mingw32-gcc +CXXFLAGS += -std=gnu++0x -Os -D_POSIX_SOURCE +CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS)) +LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) +LDLIBS := $(filter-out -lrt,$(LDLIBS)) +EXE = .exe else ifneq ($(CONFIG),none) $(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, gcc-4.6, emcc, none) @@ -192,8 +203,8 @@ top-all: $(TARGETS) $(EXTRA_TARGETS) @echo " Build successful." @echo "" -yosys: $(OBJS) - $(P) $(CXX) -o yosys $(LDFLAGS) $(OBJS) $(LDLIBS) +yosys$(EXE): $(OBJS) + $(P) $(CXX) -o yosys$(EXE) $(LDFLAGS) $(OBJS) $(LDLIBS) %.o: %.cc $(P) $(CXX) -o $@ -c $(CXXFLAGS) $< @@ -314,6 +325,13 @@ config-emcc: clean echo 'ENABLE_PLUGINS := 0' >> Makefile.conf echo 'ENABLE_READLINE := 0' >> Makefile.conf +config-mxe: clean + echo 'CONFIG := mxe' > Makefile.conf + echo 'ENABLE_TCL := 0' >> Makefile.conf + echo 'ENABLE_ABC := 0' >> Makefile.conf + echo 'ENABLE_PLUGINS := 0' >> Makefile.conf + echo 'ENABLE_READLINE := 0' >> Makefile.conf + config-gprof: clean echo 'CONFIG := gcc' > Makefile.conf echo 'ENABLE_GPROF := 1' >> Makefile.conf diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 72998f87b..9152ff22d 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -23,9 +23,9 @@ passes/techmap/techmap.inc: techlibs/common/techmap.v passes/techmap/techmap.o: passes/techmap/techmap.inc -TARGETS += yosys-filterlib +TARGETS += yosys-filterlib$(EXE) GENFILES += passes/techmap/filterlib.o -yosys-filterlib: passes/techmap/filterlib.o - $(P) $(CXX) -o yosys-filterlib $(LDFLAGS) $^ $(LDLIBS) +yosys-filterlib$(EXE): passes/techmap/filterlib.o + $(P) $(CXX) -o yosys-filterlib$(EXE) $(LDFLAGS) $^ $(LDLIBS) From d3405c15bf74b9a61968aa93ccbc61155e05585f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 9 Oct 2014 10:51:24 +0200 Subject: [PATCH 013/492] No rusage on win32 --- kernel/driver.cc | 6 +++++- kernel/log.h | 9 ++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index f26d9ef82..4210d7ca4 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -268,12 +268,16 @@ int main(int argc, char **argv) delete log_hasher; log_hasher = nullptr; + log_spacer(); +#ifdef WIN32 + log("End of script. Logfile hash: %s\n", hash.c_str()); +#else struct rusage ru_buffer; getrusage(RUSAGE_SELF, &ru_buffer); - log_spacer(); log("End of script. Logfile hash: %s, CPU: user %.2fs system %.2fs\n", hash.c_str(), ru_buffer.ru_utime.tv_sec + 1e-6 * ru_buffer.ru_utime.tv_usec, ru_buffer.ru_stime.tv_sec + 1e-6 * ru_buffer.ru_stime.tv_usec); +#endif log("%s\n", yosys_version_str); int64_t total_ns = 0; diff --git a/kernel/log.h b/kernel/log.h index 2177db095..4514c420b 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -24,7 +24,10 @@ #include #include -#include + +#ifndef WIN32 +# include +#endif // from libs/sha1/sha1.h class SHA1; @@ -154,6 +157,8 @@ struct PerformanceTimer t = 1000000000ULL * (int64_t) rusage.ru_utime.tv_sec + (int64_t) rusage.ru_utime.tv_usec * 1000ULL; t += 1000000000ULL * (int64_t) rusage.ru_stime.tv_sec + (int64_t) rusage.ru_stime.tv_usec * 1000ULL; return t; +#elif WIN32 + return 0; #else #error Dont know how to measure per-process CPU time. Need alternative method (times()/clocks()/gettimeofday()?). #endif @@ -191,8 +196,10 @@ static inline void log_dump_val_worker(int v) { log("%d", v); } static inline void log_dump_val_worker(unsigned int v) { log("%u", v); } static inline void log_dump_val_worker(long int v) { log("%ld", v); } static inline void log_dump_val_worker(unsigned long int v) { log("%lu", v); } +#ifndef WIN32 static inline void log_dump_val_worker(long long int v) { log("%lld", v); } static inline void log_dump_val_worker(unsigned long long int v) { log("%lld", v); } +#endif static inline void log_dump_val_worker(char c) { log(c >= 32 && c < 127 ? "'%c'" : "'\\x%02x'", c); } static inline void log_dump_val_worker(unsigned char c) { log(c >= 32 && c < 127 ? "'%c'" : "'\\x%02x'", c); } static inline void log_dump_val_worker(bool v) { log("%s", v ? "true" : "false"); } From 1007f5423571bee79ad3356bdd82e2f2159660ae Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 9 Oct 2014 10:52:45 +0200 Subject: [PATCH 014/492] added .exe and .html output files to .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 803e13026..90550863e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,8 +12,12 @@ /Makefile.conf /abc /yosys +/yosys.exe +/yosys.html /yosys-abc /yosys-config /yosys-filterlib +/yosys-filterlib.exe +/yosys-filterlib.html /kernel/version_*.cc /share From fea11f0fa493f227af5383cbad196c4b3585ccc4 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 9 Oct 2014 13:59:26 +0200 Subject: [PATCH 015/492] Added API for generic cell cost calculations --- kernel/cost.h | 84 +++++++++++++++++++++++++++++++++++++++++++++++ passes/abc/abc.cc | 31 ++++++++--------- 2 files changed, 100 insertions(+), 15 deletions(-) create mode 100644 kernel/cost.h diff --git a/kernel/cost.h b/kernel/cost.h new file mode 100644 index 000000000..17aca8376 --- /dev/null +++ b/kernel/cost.h @@ -0,0 +1,84 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef COST_H +#define COST_H + +#include + +YOSYS_NAMESPACE_BEGIN + +int get_cell_cost(RTLIL::Cell *cell, std::map *mod_cost_cache = nullptr); + +int get_cell_cost(RTLIL::IdString type, const std::map ¶meters = std::map(), + RTLIL::Design *design = nullptr, std::map *mod_cost_cache = nullptr) +{ + static std::map gate_cost = { + { "$_BUF_", 1 }, + { "$_NOT_", 2 }, + { "$_AND_", 4 }, + { "$_NAND_", 4 }, + { "$_OR_", 4 }, + { "$_NOR_", 4 }, + { "$_XOR_", 8 }, + { "$_XNOR_", 8 }, + { "$_AOI3_", 6 }, + { "$_OAI3_", 6 }, + { "$_AOI4_", 8 }, + { "$_OAI4_", 8 }, + { "$_MUX_", 4 } + }; + + if (gate_cost.count(type)) + return gate_cost.at(type); + + if (parameters.empty() && design && design->module(type)) + { + RTLIL::Module *mod = design->module(type); + + if (mod->attributes.count("\\cost")) + return mod->attributes.at("\\cost").as_int(); + + std::map local_mod_cost_cache; + if (mod_cost_cache == nullptr) + mod_cost_cache = &local_mod_cost_cache; + + if (mod_cost_cache->count(mod)) + return mod_cost_cache->at(mod); + + int module_cost = 1; + for (auto c : mod->cells()) + module_cost += get_cell_cost(c, mod_cost_cache); + + (*mod_cost_cache)[mod] = module_cost; + return module_cost; + } + + log("Warning: Can't determine cost of %s cell (%d parameters).\n", log_id(type), SIZE(parameters)); + return 1; +} + +int get_cell_cost(RTLIL::Cell *cell, std::map *mod_cost_cache) +{ + return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache); +} + +YOSYS_NAMESPACE_END + +#endif diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 3e1054118..487894941 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -41,6 +41,7 @@ #include "kernel/register.h" #include "kernel/sigtools.h" +#include "kernel/cost.h" #include "kernel/log.h" #include #include @@ -719,21 +720,21 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std f = fopen(p, "wt"); if (f == NULL) log_error("Opening %s for writing failed: %s\n", p, strerror(errno)); - fprintf(f, "GATE ZERO 1 Y=CONST0;\n"); - fprintf(f, "GATE ONE 1 Y=CONST1;\n"); - fprintf(f, "GATE BUF 1 Y=A; PIN * NONINV 1 999 1 0 1 0\n"); - fprintf(f, "GATE NOT 1 Y=!A; PIN * INV 1 999 1 0 1 0\n"); - fprintf(f, "GATE AND 1 Y=A*B; PIN * NONINV 1 999 1 0 1 0\n"); - fprintf(f, "GATE NAND 1 Y=!(A*B); PIN * INV 1 999 1 0 1 0\n"); - fprintf(f, "GATE OR 1 Y=A+B; PIN * NONINV 1 999 1 0 1 0\n"); - fprintf(f, "GATE NOR 1 Y=!(A+B); PIN * INV 1 999 1 0 1 0\n"); - fprintf(f, "GATE XOR 1 Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n"); - fprintf(f, "GATE XNOR 1 Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n"); - fprintf(f, "GATE MUX 1 Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n"); - fprintf(f, "GATE AOI3 1 Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n"); - fprintf(f, "GATE OAI3 1 Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n"); - fprintf(f, "GATE AOI4 1 Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n"); - fprintf(f, "GATE OAI4 1 Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n"); + fprintf(f, "GATE ZERO 1 Y=CONST0;\n"); + fprintf(f, "GATE ONE 1 Y=CONST1;\n"); + fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_BUF_")); + fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOT_")); + fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_AND_")); + fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NAND_")); + fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_OR_")); + fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOR_")); + fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XOR_")); + fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XNOR_")); + fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI3_")); + fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI3_")); + fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI4_")); + fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI4_")); + fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_MUX_")); fclose(f); free(p); From c7f5aab625bb90e766c1852592fdf42c951716c0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 9 Oct 2014 17:00:54 +0200 Subject: [PATCH 016/492] Replaced "#ifdef WIN32" with "#ifdef _WIN32" --- kernel/driver.cc | 2 +- kernel/log.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index 4210d7ca4..8a0939043 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -269,7 +269,7 @@ int main(int argc, char **argv) log_hasher = nullptr; log_spacer(); -#ifdef WIN32 +#ifdef _WIN32 log("End of script. Logfile hash: %s\n", hash.c_str()); #else struct rusage ru_buffer; diff --git a/kernel/log.h b/kernel/log.h index 4514c420b..b4182b5f3 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -25,7 +25,7 @@ #include #include -#ifndef WIN32 +#ifndef _WIN32 # include #endif @@ -157,7 +157,7 @@ struct PerformanceTimer t = 1000000000ULL * (int64_t) rusage.ru_utime.tv_sec + (int64_t) rusage.ru_utime.tv_usec * 1000ULL; t += 1000000000ULL * (int64_t) rusage.ru_stime.tv_sec + (int64_t) rusage.ru_stime.tv_usec * 1000ULL; return t; -#elif WIN32 +#elif _WIN32 return 0; #else #error Dont know how to measure per-process CPU time. Need alternative method (times()/clocks()/gettimeofday()?). @@ -196,7 +196,7 @@ static inline void log_dump_val_worker(int v) { log("%d", v); } static inline void log_dump_val_worker(unsigned int v) { log("%u", v); } static inline void log_dump_val_worker(long int v) { log("%ld", v); } static inline void log_dump_val_worker(unsigned long int v) { log("%lu", v); } -#ifndef WIN32 +#ifndef _WIN32 static inline void log_dump_val_worker(long long int v) { log("%lld", v); } static inline void log_dump_val_worker(unsigned long long int v) { log("%lld", v); } #endif From 4569a747f8af3880e23408eb93323afc8088b78b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 10 Oct 2014 16:59:44 +0200 Subject: [PATCH 017/492] Renamed SIZE() to GetSize() because of name collision on Win32 --- CodingReadme | 4 +- backends/edif/edif.cc | 2 +- backends/verilog/verilog_backend.cc | 2 +- frontends/ast/dpicall.cc | 4 +- frontends/ast/genrtlil.cc | 16 ++--- frontends/ast/simplify.cc | 20 +++--- frontends/verific/verific.cc | 16 ++--- frontends/verilog/parser.y | 2 +- kernel/calc.cc | 2 +- kernel/celltypes.h | 12 ++-- kernel/consteval.h | 20 +++--- kernel/cost.h | 2 +- kernel/log.cc | 4 +- kernel/macc.h | 58 +++++++-------- kernel/modtools.h | 6 +- kernel/rtlil.cc | 58 +++++++-------- kernel/satgen.h | 64 ++++++++--------- kernel/sigtools.h | 8 +-- kernel/utils.h | 6 +- kernel/yosys.cc | 10 +-- kernel/yosys.h | 4 +- manual/CHAPTER_Prog/stubnets.cc | 4 +- manual/PRESENTATION_Prog/my_cmd.cc | 2 +- passes/cmds/plugin.cc | 2 +- passes/cmds/show.cc | 2 +- passes/cmds/stat.cc | 10 +-- passes/fsm/fsm_extract.cc | 16 ++--- passes/fsm/fsm_map.cc | 8 +-- passes/fsm/fsm_opt.cc | 6 +- passes/fsm/fsm_recode.cc | 2 +- passes/fsm/fsmdata.h | 8 +-- passes/memory/memory_map.cc | 10 +-- passes/opt/opt_clean.cc | 8 +-- passes/opt/opt_const.cc | 28 ++++---- passes/opt/share.cc | 106 ++++++++++++++-------------- passes/opt/wreduce.cc | 84 +++++++++++----------- passes/proc/proc_arst.cc | 2 +- passes/proc/proc_rmdead.cc | 2 +- passes/sat/eval.cc | 4 +- passes/sat/sat.cc | 2 +- passes/techmap/alumacc.cc | 84 +++++++++++----------- passes/techmap/dfflibmap.cc | 2 +- passes/techmap/maccmap.cc | 66 ++++++++--------- passes/techmap/simplemap.cc | 18 ++--- passes/techmap/techmap.cc | 10 +-- passes/tests/test_abcloop.cc | 12 ++-- passes/tests/test_autotb.cc | 4 +- passes/tests/test_cell.cc | 72 +++++++++---------- 48 files changed, 447 insertions(+), 447 deletions(-) diff --git a/CodingReadme b/CodingReadme index 8f515e1f4..2404a7a5a 100644 --- a/CodingReadme +++ b/CodingReadme @@ -61,8 +61,8 @@ Yosys is written in C++11. At the moment only constructs supported by gcc 4.6 is allowed in Yosys code. This will change in future releases. In general Yosys uses "int" instead of "size_t". To avoid compiler -warnings for implicit type casts, always use "SIZE(foobar)" instead -of "foobar.size()". (the macro SIZE() is defined by kernel/yosys.h) +warnings for implicit type casts, always use "GetSize(foobar)" instead +of "foobar.size()". (GetSize() is defined by kernel/yosys.h) Use range-based for loops whenever applicable. diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 7f29cd41a..15b562ca2 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -308,7 +308,7 @@ struct EdifBackend : public Backend { *f << stringf(")\n"); for (auto &p : cell->connections()) { RTLIL::SigSpec sig = sigmap(p.second); - for (int i = 0; i < SIZE(sig); i++) + for (int i = 0; i < GetSize(sig); i++) if (sig.size() == 1) net_join_db[sig[i]].insert(stringf("(portRef %s (instanceRef %s))", EDIF_REF(p.first), EDIF_REF(cell->name))); else diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 99430d049..814c87be7 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -315,7 +315,7 @@ std::string cellname(RTLIL::Cell *cell) if (!norename && cell->name[0] == '$' && reg_ct.count(cell->type) && cell->hasPort("\\Q")) { RTLIL::SigSpec sig = cell->getPort("\\Q"); - if (SIZE(sig) != 1 || sig.is_fully_const()) + if (GetSize(sig) != 1 || sig.is_fully_const()) goto no_special_reg_name; RTLIL::Wire *wire = sig[0].wire; diff --git a/frontends/ast/dpicall.cc b/frontends/ast/dpicall.cc index e5b1ff9c0..e566d653d 100644 --- a/frontends/ast/dpicall.cc +++ b/frontends/ast/dpicall.cc @@ -75,8 +75,8 @@ AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname, log("Calling DPI function `%s' and returning `%s':\n", fname.c_str(), rtype.c_str()); - log_assert(SIZE(args) == SIZE(argtypes)); - for (int i = 0; i < SIZE(args); i++) { + log_assert(GetSize(args) == GetSize(argtypes)); + for (int i = 0; i < GetSize(args); i++) { if (argtypes[i] == "real") { log(" arg %d (%s): %f\n", i, argtypes[i].c_str(), args[i]->asReal(args[i]->is_signed)); value_store[i].f64 = args[i]->asReal(args[i]->is_signed); diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index f87a68f67..68c45179d 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -254,7 +254,7 @@ struct AST_INTERNAL::ProcessGenerator // create initial assignments for the temporary signals if ((flag_nolatches || always->get_bool_attribute("\\nolatches") || current_module->get_bool_attribute("\\nolatches")) && !found_clocked_sync) { - subst_rvalue_map = subst_lvalue_from.to_sigbit_map(RTLIL::SigSpec(RTLIL::State::Sx, SIZE(subst_lvalue_from))); + subst_rvalue_map = subst_lvalue_from.to_sigbit_map(RTLIL::SigSpec(RTLIL::State::Sx, GetSize(subst_lvalue_from))); } else { addChunkActions(current_case->actions, subst_lvalue_to, subst_lvalue_from); } @@ -289,8 +289,8 @@ struct AST_INTERNAL::ProcessGenerator { RTLIL::SigSpec new_lhs, new_rhs; - log_assert(SIZE(lhs) == SIZE(rhs)); - for (int i = 0; i < SIZE(lhs); i++) { + log_assert(GetSize(lhs) == GetSize(rhs)); + for (int i = 0; i < GetSize(lhs); i++) { if (lhs[i].wire == nullptr) continue; new_lhs.append(lhs[i]); @@ -306,7 +306,7 @@ struct AST_INTERNAL::ProcessGenerator { std::vector chunks = sig.chunks(); - for (int i = 0; i < SIZE(chunks); i++) + for (int i = 0; i < GetSize(chunks); i++) { RTLIL::SigChunk &chunk = chunks[i]; if (chunk.wire == NULL) @@ -430,7 +430,7 @@ struct AST_INTERNAL::ProcessGenerator lvalue.replace(subst_lvalue_map.stdmap()); if (ast->type == AST_ASSIGN_EQ) { - for (int i = 0; i < SIZE(unmapped_lvalue); i++) + for (int i = 0; i < GetSize(unmapped_lvalue); i++) subst_rvalue_map.set(unmapped_lvalue[i], rvalue[i]); } @@ -472,7 +472,7 @@ struct AST_INTERNAL::ProcessGenerator subst_lvalue_map.save(); subst_rvalue_map.save(); - for (int i = 0; i < SIZE(this_case_eq_lvalue); i++) + for (int i = 0; i < GetSize(this_case_eq_lvalue); i++) subst_lvalue_map.set(this_case_eq_lvalue[i], this_case_eq_ltemp[i]); RTLIL::CaseRule *backup_case = current_case; @@ -507,7 +507,7 @@ struct AST_INTERNAL::ProcessGenerator sw->cases.push_back(default_case); } - for (int i = 0; i < SIZE(this_case_eq_lvalue); i++) + for (int i = 0; i < GetSize(this_case_eq_lvalue); i++) subst_rvalue_map.set(this_case_eq_lvalue[i], this_case_eq_ltemp[i]); this_case_eq_lvalue.replace(subst_lvalue_map.stdmap()); @@ -941,7 +941,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) shift_val = current_module->Sub(NEW_ID, RTLIL::SigSpec(source_width - width), shift_val, fake_ast->children[1]->is_signed); fake_ast->children[1]->is_signed = true; } - if (SIZE(shift_val) >= 32) + if (GetSize(shift_val) >= 32) fake_ast->children[1]->is_signed = true; RTLIL::SigSpec sig = binop2rtlil(fake_ast, "$shiftx", width, fake_ast->children[0]->genRTLIL(), shift_val); delete left_at_zero_ast; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 969cc2302..9f33ea780 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -575,9 +575,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, { AstNode *index_expr = nullptr; - for (int i = 0; 2*i < SIZE(id2ast->multirange_dimensions); i++) + for (int i = 0; 2*i < GetSize(id2ast->multirange_dimensions); i++) { - if (SIZE(children[0]->children) < i) + if (GetSize(children[0]->children) < i) log_error("Insufficient number of array indices for %s at %s:%d.\n", log_id(str), filename.c_str(), linenum); AstNode *new_index_expr = children[0]->children[i]->children.at(0)->clone(); @@ -591,7 +591,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, index_expr = new AstNode(AST_ADD, new AstNode(AST_MUL, index_expr, AstNode::mkconst_int(id2ast->multirange_dimensions[2*i-1], true)), new_index_expr); } - for (int i = SIZE(id2ast->multirange_dimensions)/1; i < SIZE(children[0]->children); i++) + for (int i = GetSize(id2ast->multirange_dimensions)/1; i < GetSize(children[0]->children); i++) children.push_back(children[0]->children[i]->clone()); delete children[0]; @@ -1366,7 +1366,7 @@ skip_dynamic_range_lvalue_expansion:; RTLIL::Const arg_value = buf->bitsAsConst(); if (arg_value.as_bool()) - arg_value = const_sub(arg_value, 1, false, false, SIZE(arg_value)); + arg_value = const_sub(arg_value, 1, false, false, GetSize(arg_value)); delete buf; uint32_t result = 0; @@ -1455,9 +1455,9 @@ skip_dynamic_range_lvalue_expansion:; rtype = RTLIL::unescape_id(dpi_decl->children.at(0)->str); fname = RTLIL::unescape_id(dpi_decl->children.at(1)->str); - for (int i = 2; i < SIZE(dpi_decl->children); i++) + for (int i = 2; i < GetSize(dpi_decl->children); i++) { - if (i-2 >= SIZE(children)) + if (i-2 >= GetSize(children)) log_error("Insufficient number of arguments in DPI function call at %s:%d.\n", filename.c_str(), linenum); argtypes.push_back(RTLIL::unescape_id(dpi_decl->children.at(i)->str)); @@ -1558,7 +1558,7 @@ skip_dynamic_range_lvalue_expansion:; celltype = RTLIL::escape_id(celltype); AstNode *cell = new AstNode(AST_CELL, new AstNode(AST_CELLTYPE)); - cell->str = prefix.substr(0, SIZE(prefix)-1); + cell->str = prefix.substr(0, GetSize(prefix)-1); cell->children[0]->str = celltype; for (auto attr : decl->attributes) @@ -1681,7 +1681,7 @@ skip_dynamic_range_lvalue_expansion:; bool param_upto = current_scope[str]->range_valid && current_scope[str]->range_swapped; int param_offset = current_scope[str]->range_valid ? current_scope[str]->range_right : 0; int param_width = current_scope[str]->range_valid ? current_scope[str]->range_left - current_scope[str]->range_right + 1 : - SIZE(current_scope[str]->children[0]->bits); + GetSize(current_scope[str]->children[0]->bits); int tmp_range_left = children[0]->range_left, tmp_range_right = children[0]->range_right; if (param_upto) { tmp_range_left = (param_width + 2*param_offset) - children[0]->range_right - 1; @@ -1847,7 +1847,7 @@ skip_dynamic_range_lvalue_expansion:; if (children[0]->type == AST_CONSTANT && children[0]->bits_only_01()) { std::vector new_children; new_children.push_back(children[0]); - for (int i = 1; i < SIZE(children); i++) { + for (int i = 1; i < GetSize(children); i++) { AstNode *child = children[i]; log_assert(child->type == AST_COND); for (auto v : child->children) { @@ -1857,7 +1857,7 @@ skip_dynamic_range_lvalue_expansion:; continue; if (v->type == AST_CONSTANT && v->bits_only_01()) { if (v->bits == children[0]->bits) { - while (i+1 < SIZE(children)) + while (i+1 < GetSize(children)) delete children[++i]; goto keep_const_cond; } diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index d0f148386..5e1894cfd 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -324,7 +324,7 @@ static bool import_netlist_instance_cells(RTLIL::Module *module, std::mapGetCin()->IsGnd()) { module->addAdd(RTLIL::escape_id(inst->Name()), IN1, IN2, out, SIGNED); } else { - RTLIL::SigSpec tmp = module->addWire(NEW_ID, SIZE(out)); + RTLIL::SigSpec tmp = module->addWire(NEW_ID, GetSize(out)); module->addAdd(NEW_ID, IN1, IN2, tmp, SIGNED); module->addAdd(RTLIL::escape_id(inst->Name()), tmp, net_map.at(inst->GetCin()), out, false); } @@ -687,8 +687,8 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::setparameters["\\CLK_ENABLE"] = false; cell->parameters["\\CLK_POLARITY"] = true; cell->parameters["\\TRANSPARENT"] = false; - cell->parameters["\\ABITS"] = SIZE(addr); - cell->parameters["\\WIDTH"] = SIZE(data); + cell->parameters["\\ABITS"] = GetSize(addr); + cell->parameters["\\WIDTH"] = GetSize(data); cell->setPort("\\CLK", RTLIL::State::S0); cell->setPort("\\ADDR", addr); cell->setPort("\\DATA", data); @@ -709,9 +709,9 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::setparameters["\\CLK_ENABLE"] = false; cell->parameters["\\CLK_POLARITY"] = true; cell->parameters["\\PRIORITY"] = 0; - cell->parameters["\\ABITS"] = SIZE(addr); - cell->parameters["\\WIDTH"] = SIZE(data); - cell->setPort("\\EN", RTLIL::SigSpec(net_map.at(inst->GetControl())).repeat(SIZE(data))); + cell->parameters["\\ABITS"] = GetSize(addr); + cell->parameters["\\WIDTH"] = GetSize(data); + cell->setPort("\\EN", RTLIL::SigSpec(net_map.at(inst->GetControl())).repeat(GetSize(data))); cell->setPort("\\CLK", RTLIL::State::S0); cell->setPort("\\ADDR", addr); cell->setPort("\\DATA", data); @@ -753,9 +753,9 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::sethasPort(RTLIL::escape_id(port_name))) conn = cell->getPort(RTLIL::escape_id(port_name)); - while (SIZE(conn) <= port_offset) { + while (GetSize(conn) <= port_offset) { if (pr->GetPort()->GetDir() != DIR_IN) - conn.append(module->addWire(NEW_ID, port_offset - SIZE(conn))); + conn.append(module->addWire(NEW_ID, port_offset - GetSize(conn))); conn.append(RTLIL::State::Sz); } conn.replace(port_offset, net_map.at(pr->GetNet())); diff --git a/frontends/verilog/parser.y b/frontends/verilog/parser.y index a9f69a49c..cf02a56a9 100644 --- a/frontends/verilog/parser.y +++ b/frontends/verilog/parser.y @@ -142,7 +142,7 @@ input: { ast_stack.push_back(current_ast); } design { ast_stack.pop_back(); - log_assert(SIZE(ast_stack) == 0); + log_assert(GetSize(ast_stack) == 0); for (auto &it : default_attr_list) delete it.second; default_attr_list.clear(); diff --git a/kernel/calc.cc b/kernel/calc.cc index 41179d045..aa3e8b919 100644 --- a/kernel/calc.cc +++ b/kernel/calc.cc @@ -303,7 +303,7 @@ RTLIL::Const RTLIL::const_shl(const RTLIL::Const &arg1, const RTLIL::Const &arg2 RTLIL::Const RTLIL::const_shr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool, int result_len) { RTLIL::Const arg1_ext = arg1; - extend_u0(arg1_ext, std::max(result_len, SIZE(arg1)), signed1); + extend_u0(arg1_ext, std::max(result_len, GetSize(arg1)), signed1); return const_shift_worker(arg1_ext, arg2, false, +1, result_len); } diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 2774073dc..3d9e4cf93 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -303,7 +303,7 @@ struct CellTypes int width = cell->parameters.at("\\WIDTH").as_int(); std::vector t = cell->parameters.at("\\LUT").bits; - while (SIZE(t) < (1 << width)) + while (GetSize(t) < (1 << width)) t.push_back(RTLIL::S0); t.resize(1 << width); @@ -311,16 +311,16 @@ struct CellTypes RTLIL::State sel = arg1.bits.at(i); std::vector new_t; if (sel == RTLIL::S0) - new_t = std::vector(t.begin(), t.begin() + SIZE(t)/2); + new_t = std::vector(t.begin(), t.begin() + GetSize(t)/2); else if (sel == RTLIL::S1) - new_t = std::vector(t.begin() + SIZE(t)/2, t.end()); + new_t = std::vector(t.begin() + GetSize(t)/2, t.end()); else - for (int j = 0; j < SIZE(t)/2; j++) - new_t.push_back(t[j] == t[j + SIZE(t)/2] ? t[j] : RTLIL::Sx); + for (int j = 0; j < GetSize(t)/2; j++) + new_t.push_back(t[j] == t[j + GetSize(t)/2] ? t[j] : RTLIL::Sx); t.swap(new_t); } - log_assert(SIZE(t) == 1); + log_assert(GetSize(t) == 1); return t; } diff --git a/kernel/consteval.h b/kernel/consteval.h index 12895ec78..c2e9710fb 100644 --- a/kernel/consteval.h +++ b/kernel/consteval.h @@ -74,7 +74,7 @@ struct ConstEval assign_map.apply(sig); #ifndef NDEBUG RTLIL::SigSpec current_val = values_map(sig); - for (int i = 0; i < SIZE(current_val); i++) + for (int i = 0; i < GetSize(current_val); i++) log_assert(current_val[i].wire != NULL || current_val[i] == value.bits[i]); #endif values_map.add(sig, RTLIL::SigSpec(value)); @@ -109,10 +109,10 @@ struct ConstEval if (sig_p.is_fully_def() && sig_g.is_fully_def() && sig_ci.is_fully_def()) { - RTLIL::Const coval(RTLIL::Sx, SIZE(sig_co)); + RTLIL::Const coval(RTLIL::Sx, GetSize(sig_co)); bool carry = sig_ci.as_bool(); - for (int i = 0; i < SIZE(coval); i++) { + for (int i = 0; i < GetSize(coval); i++) { carry = (sig_g[i] == RTLIL::S1) || (sig_p[i] == RTLIL::S1 && carry); coval.bits[i] = carry ? RTLIL::S1 : RTLIL::S0; } @@ -120,7 +120,7 @@ struct ConstEval set(sig_co, coval); } else - set(sig_co, RTLIL::Const(RTLIL::Sx, SIZE(sig_co))); + set(sig_co, RTLIL::Const(RTLIL::Sx, GetSize(sig_co))); return true; } @@ -198,7 +198,7 @@ struct ConstEval { RTLIL::SigSpec sig_c = cell->getPort("\\C"); RTLIL::SigSpec sig_x = cell->getPort("\\X"); - int width = SIZE(sig_c); + int width = GetSize(sig_c); if (!eval(sig_a, undef, cell)) return false; @@ -216,7 +216,7 @@ struct ConstEval RTLIL::Const t3 = const_and(sig_c.as_const(), t1, false, false, width); RTLIL::Const val_x = const_or(t2, t3, false, false, width); - for (int i = 0; i < SIZE(val_y); i++) + for (int i = 0; i < GetSize(val_y); i++) if (val_y.bits[i] == RTLIL::Sx) val_x.bits[i] = RTLIL::Sx; @@ -247,13 +247,13 @@ struct ConstEval RTLIL::SigSpec sig_co = cell->getPort("\\CO"); bool any_input_undef = !(sig_a.is_fully_def() && sig_b.is_fully_def() && sig_ci.is_fully_def() && sig_bi.is_fully_def()); - sig_a.extend_u0(SIZE(sig_y), signed_a); - sig_b.extend_u0(SIZE(sig_y), signed_b); + sig_a.extend_u0(GetSize(sig_y), signed_a); + sig_b.extend_u0(GetSize(sig_y), signed_b); bool carry = sig_ci[0] == RTLIL::S1; bool b_inv = sig_bi[0] == RTLIL::S1; - for (int i = 0; i < SIZE(sig_y); i++) + for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::SigSpec x_inputs = { sig_a[i], sig_b[i], sig_bi[0] }; @@ -294,7 +294,7 @@ struct ConstEval return false; } - RTLIL::Const result(0, SIZE(cell->getPort("\\Y"))); + RTLIL::Const result(0, GetSize(cell->getPort("\\Y"))); if (!macc.eval(result)) log_abort(); diff --git a/kernel/cost.h b/kernel/cost.h index 17aca8376..5e99df993 100644 --- a/kernel/cost.h +++ b/kernel/cost.h @@ -70,7 +70,7 @@ int get_cell_cost(RTLIL::IdString type, const std::mapupdate(str); diff --git a/kernel/macc.h b/kernel/macc.h index 7d70a2686..ab17f8c41 100644 --- a/kernel/macc.h +++ b/kernel/macc.h @@ -42,20 +42,20 @@ struct Macc for (auto &port : ports) { - if (SIZE(port.in_a) == 0 && SIZE(port.in_b) == 0) + if (GetSize(port.in_a) == 0 && GetSize(port.in_b) == 0) continue; - if (SIZE(port.in_a) < SIZE(port.in_b)) + if (GetSize(port.in_a) < GetSize(port.in_b)) std::swap(port.in_a, port.in_b); - if (SIZE(port.in_a) == 1 && SIZE(port.in_b) == 0 && !port.is_signed && !port.do_subtract) { + if (GetSize(port.in_a) == 1 && GetSize(port.in_b) == 0 && !port.is_signed && !port.do_subtract) { bit_ports.append(port.in_a); continue; } if (port.in_a.is_fully_const() && port.in_b.is_fully_const()) { RTLIL::Const v = port.in_a.as_const(); - if (SIZE(port.in_b)) + if (GetSize(port.in_b)) v = const_mul(v, port.in_b.as_const(), port.is_signed, port.is_signed, width); if (port.do_subtract) off = const_sub(off, v, port.is_signed, port.is_signed, width); @@ -65,15 +65,15 @@ struct Macc } if (port.is_signed) { - while (SIZE(port.in_a) > 1 && port.in_a[SIZE(port.in_a)-1] == port.in_a[SIZE(port.in_a)-2]) - port.in_a.remove(SIZE(port.in_a)-1); - while (SIZE(port.in_b) > 1 && port.in_b[SIZE(port.in_b)-1] == port.in_b[SIZE(port.in_b)-2]) - port.in_b.remove(SIZE(port.in_b)-1); + while (GetSize(port.in_a) > 1 && port.in_a[GetSize(port.in_a)-1] == port.in_a[GetSize(port.in_a)-2]) + port.in_a.remove(GetSize(port.in_a)-1); + while (GetSize(port.in_b) > 1 && port.in_b[GetSize(port.in_b)-1] == port.in_b[GetSize(port.in_b)-2]) + port.in_b.remove(GetSize(port.in_b)-1); } else { - while (SIZE(port.in_a) > 1 && port.in_a[SIZE(port.in_a)-1] == RTLIL::S0) - port.in_a.remove(SIZE(port.in_a)-1); - while (SIZE(port.in_b) > 1 && port.in_b[SIZE(port.in_b)-1] == RTLIL::S0) - port.in_b.remove(SIZE(port.in_b)-1); + while (GetSize(port.in_a) > 1 && port.in_a[GetSize(port.in_a)-1] == RTLIL::S0) + port.in_a.remove(GetSize(port.in_a)-1); + while (GetSize(port.in_b) > 1 && port.in_b[GetSize(port.in_b)-1] == RTLIL::S0) + port.in_b.remove(GetSize(port.in_b)-1); } new_ports.push_back(port); @@ -108,7 +108,7 @@ struct Macc int config_width = cell->getParam("\\CONFIG_WIDTH").as_int(); int config_cursor = 0; - log_assert(SIZE(config_bits) >= config_width); + log_assert(GetSize(config_bits) >= config_width); int num_bits = 0; if (config_bits[config_cursor++] == RTLIL::S1) num_bits |= 1; @@ -117,7 +117,7 @@ struct Macc if (config_bits[config_cursor++] == RTLIL::S1) num_bits |= 8; int port_a_cursor = 0; - while (port_a_cursor < SIZE(port_a)) + while (port_a_cursor < GetSize(port_a)) { log_assert(config_cursor + 2 + 2*num_bits <= config_width); @@ -146,7 +146,7 @@ struct Macc } log_assert(config_cursor == config_width); - log_assert(port_a_cursor == SIZE(port_a)); + log_assert(port_a_cursor == GetSize(port_a)); } void to_cell(RTLIL::Cell *cell) const @@ -156,8 +156,8 @@ struct Macc int max_size = 0, num_bits = 0; for (auto &port : ports) { - max_size = std::max(max_size, SIZE(port.in_a)); - max_size = std::max(max_size, SIZE(port.in_b)); + max_size = std::max(max_size, GetSize(port.in_a)); + max_size = std::max(max_size, GetSize(port.in_b)); } while (max_size) @@ -171,17 +171,17 @@ struct Macc for (auto &port : ports) { - if (SIZE(port.in_a) == 0) + if (GetSize(port.in_a) == 0) continue; config_bits.push_back(port.is_signed ? RTLIL::S1 : RTLIL::S0); config_bits.push_back(port.do_subtract ? RTLIL::S1 : RTLIL::S0); - int size_a = SIZE(port.in_a); + int size_a = GetSize(port.in_a); for (int i = 0; i < num_bits; i++) config_bits.push_back(size_a & (1 << i) ? RTLIL::S1 : RTLIL::S0); - int size_b = SIZE(port.in_b); + int size_b = GetSize(port.in_b); for (int i = 0; i < num_bits; i++) config_bits.push_back(size_b & (1 << i) ? RTLIL::S1 : RTLIL::S0); @@ -192,9 +192,9 @@ struct Macc cell->setPort("\\A", port_a); cell->setPort("\\B", bit_ports); cell->setParam("\\CONFIG", config_bits); - cell->setParam("\\CONFIG_WIDTH", SIZE(config_bits)); - cell->setParam("\\A_WIDTH", SIZE(port_a)); - cell->setParam("\\B_WIDTH", SIZE(bit_ports)); + cell->setParam("\\CONFIG_WIDTH", GetSize(config_bits)); + cell->setParam("\\A_WIDTH", GetSize(port_a)); + cell->setParam("\\B_WIDTH", GetSize(bit_ports)); } bool eval(RTLIL::Const &result) const @@ -208,21 +208,21 @@ struct Macc return false; RTLIL::Const summand; - if (SIZE(port.in_b) == 0) - summand = const_pos(port.in_a.as_const(), port.in_b.as_const(), port.is_signed, port.is_signed, SIZE(result)); + if (GetSize(port.in_b) == 0) + summand = const_pos(port.in_a.as_const(), port.in_b.as_const(), port.is_signed, port.is_signed, GetSize(result)); else - summand = const_mul(port.in_a.as_const(), port.in_b.as_const(), port.is_signed, port.is_signed, SIZE(result)); + summand = const_mul(port.in_a.as_const(), port.in_b.as_const(), port.is_signed, port.is_signed, GetSize(result)); if (port.do_subtract) - result = const_sub(result, summand, port.is_signed, port.is_signed, SIZE(result)); + result = const_sub(result, summand, port.is_signed, port.is_signed, GetSize(result)); else - result = const_add(result, summand, port.is_signed, port.is_signed, SIZE(result)); + result = const_add(result, summand, port.is_signed, port.is_signed, GetSize(result)); } for (auto bit : bit_ports) { if (bit.wire) return false; - result = const_add(result, bit.data, false, false, SIZE(result)); + result = const_add(result, bit.data, false, false, GetSize(result)); } return true; diff --git a/kernel/modtools.h b/kernel/modtools.h index 58cdd5b0e..1b6968d74 100644 --- a/kernel/modtools.h +++ b/kernel/modtools.h @@ -59,7 +59,7 @@ struct ModIndex : public RTLIL::Monitor void port_add(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &sig) { - for (int i = 0; i < SIZE(sig); i++) { + for (int i = 0; i < GetSize(sig); i++) { RTLIL::SigBit bit = sigmap(sig[i]); if (bit.wire) database[bit].ports.insert(PortInfo(cell, port, i)); @@ -68,7 +68,7 @@ struct ModIndex : public RTLIL::Monitor void port_del(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &sig) { - for (int i = 0; i < SIZE(sig); i++) { + for (int i = 0; i < GetSize(sig); i++) { RTLIL::SigBit bit = sigmap(sig[i]); if (bit.wire) database[bit].ports.erase(PortInfo(cell, port, i)); @@ -88,7 +88,7 @@ struct ModIndex : public RTLIL::Monitor database.clear(); for (auto wire : module->wires()) if (wire->port_input || wire->port_output) - for (int i = 0; i < SIZE(wire); i++) { + for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit bit = sigmap(RTLIL::SigBit(wire, i)); if (bit.wire && wire->port_input) database[bit].is_input = true; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 89132ea29..28f0dfdc5 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -941,10 +941,10 @@ void RTLIL::Module::check() for (auto &it2 : it.second->attributes) log_assert(!it2.first.empty()); if (it.second->port_id) { - log_assert(SIZE(ports) >= it.second->port_id); + log_assert(GetSize(ports) >= it.second->port_id); log_assert(ports.at(it.second->port_id-1) == it.first); log_assert(it.second->port_input || it.second->port_output); - if (SIZE(ports_declared) < it.second->port_id) + if (GetSize(ports_declared) < it.second->port_id) ports_declared.resize(it.second->port_id); log_assert(ports_declared[it.second->port_id-1] == false); ports_declared[it.second->port_id-1] = true; @@ -953,7 +953,7 @@ void RTLIL::Module::check() } for (auto port_declared : ports_declared) log_assert(port_declared == true); - log_assert(SIZE(ports) == SIZE(ports_declared)); + log_assert(GetSize(ports) == GetSize(ports_declared)); for (auto &it : memories) { log_assert(it.first == it.second->name); @@ -1811,25 +1811,25 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed) return; if (type == "$mux" || type == "$pmux") { - parameters["\\WIDTH"] = SIZE(connections_["\\Y"]); + parameters["\\WIDTH"] = GetSize(connections_["\\Y"]); if (type == "$pmux") - parameters["\\S_WIDTH"] = SIZE(connections_["\\S"]); + parameters["\\S_WIDTH"] = GetSize(connections_["\\S"]); check(); return; } if (type == "$lut") { - parameters["\\WIDTH"] = SIZE(connections_["\\A"]); + parameters["\\WIDTH"] = GetSize(connections_["\\A"]); return; } if (type == "$fa") { - parameters["\\WIDTH"] = SIZE(connections_["\\Y"]); + parameters["\\WIDTH"] = GetSize(connections_["\\Y"]); return; } if (type == "$lcu") { - parameters["\\WIDTH"] = SIZE(connections_["\\CO"]); + parameters["\\WIDTH"] = GetSize(connections_["\\CO"]); return; } @@ -1842,7 +1842,7 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed) else if (parameters.count("\\A_SIGNED") == 0) parameters["\\A_SIGNED"] = false; } - parameters["\\A_WIDTH"] = SIZE(connections_["\\A"]); + parameters["\\A_WIDTH"] = GetSize(connections_["\\A"]); } if (connections_.count("\\B")) { @@ -1852,11 +1852,11 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed) else if (parameters.count("\\B_SIGNED") == 0) parameters["\\B_SIGNED"] = false; } - parameters["\\B_WIDTH"] = SIZE(connections_["\\B"]); + parameters["\\B_WIDTH"] = GetSize(connections_["\\B"]); } if (connections_.count("\\Y")) - parameters["\\Y_WIDTH"] = SIZE(connections_["\\Y"]); + parameters["\\Y_WIDTH"] = GetSize(connections_["\\Y"]); check(); } @@ -1872,7 +1872,7 @@ RTLIL::SigChunk::SigChunk(const RTLIL::Const &value) { wire = NULL; data = value.bits; - width = SIZE(data); + width = GetSize(data); offset = 0; } @@ -1896,7 +1896,7 @@ RTLIL::SigChunk::SigChunk(const std::string &str) { wire = NULL; data = RTLIL::Const(str).bits; - width = SIZE(data); + width = GetSize(data); offset = 0; } @@ -1904,7 +1904,7 @@ RTLIL::SigChunk::SigChunk(int val, int width) { wire = NULL; data = RTLIL::Const(val, width).bits; - this->width = SIZE(data); + this->width = GetSize(data); offset = 0; } @@ -1912,7 +1912,7 @@ RTLIL::SigChunk::SigChunk(RTLIL::State bit, int width) { wire = NULL; data = RTLIL::Const(bit, width).bits; - this->width = SIZE(data); + this->width = GetSize(data); offset = 0; } @@ -2258,7 +2258,7 @@ void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec std::map rules; - for (int i = 0; i < SIZE(pattern.bits_); i++) + for (int i = 0; i < GetSize(pattern.bits_); i++) if (pattern.bits_[i].wire != NULL) rules[pattern.bits_[i]] = with.bits_[i]; @@ -2280,7 +2280,7 @@ void RTLIL::SigSpec::replace(const std::map &rules unpack(); other->unpack(); - for (int i = 0; i < SIZE(bits_); i++) { + for (int i = 0; i < GetSize(bits_); i++) { auto it = rules.find(bits_[i]); if (it != rules.end()) other->bits_[i] = it->second; @@ -2333,12 +2333,12 @@ void RTLIL::SigSpec::remove2(const std::set &pattern, RTLIL::SigS std::vector new_bits, new_other_bits; - new_bits.resize(SIZE(bits_)); + new_bits.resize(GetSize(bits_)); if (other != NULL) - new_other_bits.resize(SIZE(bits_)); + new_other_bits.resize(GetSize(bits_)); int k = 0; - for (int i = 0; i < SIZE(bits_); i++) { + for (int i = 0; i < GetSize(bits_); i++) { if (bits_[i].wire != NULL && pattern.count(bits_[i])) continue; if (other != NULL) @@ -2351,11 +2351,11 @@ void RTLIL::SigSpec::remove2(const std::set &pattern, RTLIL::SigS new_other_bits.resize(k); bits_.swap(new_bits); - width_ = SIZE(bits_); + width_ = GetSize(bits_); if (other != NULL) { other->bits_.swap(new_other_bits); - other->width_ = SIZE(other->bits_); + other->width_ = GetSize(other->bits_); } check(); @@ -2418,7 +2418,7 @@ void RTLIL::SigSpec::remove_const() cover("kernel.rtlil.sigspec.remove_const.packed"); std::vector new_chunks; - new_chunks.reserve(SIZE(chunks_)); + new_chunks.reserve(GetSize(chunks_)); width_ = 0; for (auto &chunk : chunks_) @@ -2624,7 +2624,7 @@ void RTLIL::SigSpec::check() const { cover("kernel.rtlil.sigspec.check.unpacked"); - log_assert(width_ == SIZE(bits_)); + log_assert(width_ == GetSize(bits_)); log_assert(chunks_.empty()); } } @@ -2699,7 +2699,7 @@ bool RTLIL::SigSpec::is_wire() const cover("kernel.rtlil.sigspec.is_wire"); pack(); - return SIZE(chunks_) == 1 && chunks_[0].wire && chunks_[0].wire->width == width_; + return GetSize(chunks_) == 1 && chunks_[0].wire && chunks_[0].wire->width == width_; } bool RTLIL::SigSpec::is_chunk() const @@ -2707,7 +2707,7 @@ bool RTLIL::SigSpec::is_chunk() const cover("kernel.rtlil.sigspec.is_chunk"); pack(); - return SIZE(chunks_) == 1; + return GetSize(chunks_) == 1; } bool RTLIL::SigSpec::is_fully_const() const @@ -2770,7 +2770,7 @@ bool RTLIL::SigSpec::as_bool() const cover("kernel.rtlil.sigspec.as_bool"); pack(); - log_assert(is_fully_const() && SIZE(chunks_) <= 1); + log_assert(is_fully_const() && GetSize(chunks_) <= 1); if (width_) return RTLIL::Const(chunks_[0].data).as_bool(); return false; @@ -2781,7 +2781,7 @@ int RTLIL::SigSpec::as_int(bool is_signed) const cover("kernel.rtlil.sigspec.as_int"); pack(); - log_assert(is_fully_const() && SIZE(chunks_) <= 1); + log_assert(is_fully_const() && GetSize(chunks_) <= 1); if (width_) return RTLIL::Const(chunks_[0].data).as_int(is_signed); return 0; @@ -2809,7 +2809,7 @@ RTLIL::Const RTLIL::SigSpec::as_const() const cover("kernel.rtlil.sigspec.as_const"); pack(); - log_assert(is_fully_const() && SIZE(chunks_) <= 1); + log_assert(is_fully_const() && GetSize(chunks_) <= 1); if (width_) return chunks_[0].data; return RTLIL::Const(); diff --git a/kernel/satgen.h b/kernel/satgen.h index d4933050f..2759b3927 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -59,7 +59,7 @@ struct SatGen sigmap->apply(sig); std::vector vec; - vec.reserve(SIZE(sig)); + vec.reserve(GetSize(sig)); for (auto &bit : sig) if (bit.wire == NULL) { @@ -791,24 +791,24 @@ struct SatGen Macc macc; macc.from_cell(cell); - std::vector tmp(SIZE(y), ez->FALSE); + std::vector tmp(GetSize(y), ez->FALSE); for (auto &port : macc.ports) { std::vector in_a = importDefSigSpec(port.in_a, timestep); std::vector in_b = importDefSigSpec(port.in_b, timestep); - while (SIZE(in_a) < SIZE(y)) + while (GetSize(in_a) < GetSize(y)) in_a.push_back(port.is_signed && !in_a.empty() ? in_a.back() : ez->FALSE); - in_a.resize(SIZE(y)); + in_a.resize(GetSize(y)); - if (SIZE(in_b)) + if (GetSize(in_b)) { - while (SIZE(in_b) < SIZE(y)) + while (GetSize(in_b) < GetSize(y)) in_b.push_back(port.is_signed && !in_b.empty() ? in_b.back() : ez->FALSE); - in_b.resize(SIZE(y)); + in_b.resize(GetSize(y)); - for (int i = 0; i < SIZE(in_b); i++) { + for (int i = 0; i < GetSize(in_b); i++) { std::vector shifted_a(in_a.size(), ez->FALSE); for (int j = i; j < int(in_a.size()); j++) shifted_a.at(j) = in_a.at(j-i); @@ -827,8 +827,8 @@ struct SatGen } } - for (int i = 0; i < SIZE(b); i++) { - std::vector val(SIZE(y), ez->FALSE); + for (int i = 0; i < GetSize(b); i++) { + std::vector val(GetSize(y), ez->FALSE); val.at(0) = b.at(i); tmp = ez->vec_add(tmp, val); } @@ -842,7 +842,7 @@ struct SatGen int undef_any_b = ez->expression(ezSAT::OpOr, undef_b); std::vector undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep); - ez->assume(ez->vec_eq(undef_y, std::vector(SIZE(y), ez->OR(undef_any_a, undef_any_b)))); + ez->assume(ez->vec_eq(undef_y, std::vector(GetSize(y), ez->OR(undef_any_a, undef_any_b)))); undefGating(y, tmp, undef_y); } @@ -940,43 +940,43 @@ struct SatGen std::vector lut; for (auto bit : cell->getParam("\\LUT").bits) lut.push_back(bit == RTLIL::S1 ? ez->TRUE : ez->FALSE); - while (SIZE(lut) < (1 << SIZE(a))) + while (GetSize(lut) < (1 << GetSize(a))) lut.push_back(ez->FALSE); - lut.resize(1 << SIZE(a)); + lut.resize(1 << GetSize(a)); if (model_undef) { std::vector undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep); - std::vector t(lut), u(SIZE(t), ez->FALSE); + std::vector t(lut), u(GetSize(t), ez->FALSE); - for (int i = SIZE(a)-1; i >= 0; i--) + for (int i = GetSize(a)-1; i >= 0; i--) { - std::vector t0(t.begin(), t.begin() + SIZE(t)/2); - std::vector t1(t.begin() + SIZE(t)/2, t.end()); + std::vector t0(t.begin(), t.begin() + GetSize(t)/2); + std::vector t1(t.begin() + GetSize(t)/2, t.end()); - std::vector u0(u.begin(), u.begin() + SIZE(u)/2); - std::vector u1(u.begin() + SIZE(u)/2, u.end()); + std::vector u0(u.begin(), u.begin() + GetSize(u)/2); + std::vector u1(u.begin() + GetSize(u)/2, u.end()); t = ez->vec_ite(a[i], t1, t0); u = ez->vec_ite(undef_a[i], ez->vec_or(ez->vec_xor(t0, t1), ez->vec_or(u0, u1)), ez->vec_ite(a[i], u1, u0)); } - log_assert(SIZE(t) == 1); - log_assert(SIZE(u) == 1); + log_assert(GetSize(t) == 1); + log_assert(GetSize(u) == 1); undefGating(y, t, u); ez->assume(ez->vec_eq(importUndefSigSpec(cell->getPort("\\Y"), timestep), u)); } else { std::vector t = lut; - for (int i = SIZE(a)-1; i >= 0; i--) + for (int i = GetSize(a)-1; i >= 0; i--) { - std::vector t0(t.begin(), t.begin() + SIZE(t)/2); - std::vector t1(t.begin() + SIZE(t)/2, t.end()); + std::vector t0(t.begin(), t.begin() + GetSize(t)/2); + std::vector t1(t.begin() + GetSize(t)/2, t.end()); t = ez->vec_ite(a[i], t1, t0); } - log_assert(SIZE(t) == 1); + log_assert(GetSize(t) == 1); ez->assume(ez->vec_eq(y, t)); } return true; @@ -1027,7 +1027,7 @@ struct SatGen std::vector yy = model_undef ? ez->vec_var(co.size()) : co; - for (int i = 0; i < SIZE(co); i++) + for (int i = 0; i < GetSize(co); i++) ez->SET(yy[i], ez->OR(g[i], ez->AND(p[i], i ? yy[i-1] : ci[0]))); if (model_undef) @@ -1068,12 +1068,12 @@ struct SatGen std::vector def_x = model_undef ? ez->vec_var(x.size()) : x; std::vector def_co = model_undef ? ez->vec_var(co.size()) : co; - log_assert(SIZE(y) == SIZE(x)); - log_assert(SIZE(y) == SIZE(co)); - log_assert(SIZE(ci) == 1); - log_assert(SIZE(bi) == 1); + log_assert(GetSize(y) == GetSize(x)); + log_assert(GetSize(y) == GetSize(co)); + log_assert(GetSize(ci) == 1); + log_assert(GetSize(bi) == 1); - for (int i = 0; i < SIZE(y); i++) + for (int i = 0; i < GetSize(y); i++) { int s1 = a.at(i), s2 = ez->XOR(b.at(i), bi.at(0)), s3 = i ? co.at(i-1) : ci.at(0); ez->SET(def_x.at(i), ez->XOR(s1, s2)); @@ -1103,7 +1103,7 @@ struct SatGen all_inputs_undef.insert(all_inputs_undef.end(), undef_bi.begin(), undef_bi.end()); int undef_any = ez->expression(ezSAT::OpOr, all_inputs_undef); - for (int i = 0; i < SIZE(undef_y); i++) { + for (int i = 0; i < GetSize(undef_y); i++) { ez->SET(undef_y.at(i), undef_any); ez->SET(undef_x.at(i), ez->OR(undef_a.at(i), undef_b.at(i), undef_bi.at(0))); ez->SET(undef_co.at(i), undef_any); diff --git a/kernel/sigtools.h b/kernel/sigtools.h index 32ef444aa..c3c6a8db1 100644 --- a/kernel/sigtools.h +++ b/kernel/sigtools.h @@ -66,8 +66,8 @@ struct SigPool void expand(RTLIL::SigSpec from, RTLIL::SigSpec to) { - log_assert(SIZE(from) == SIZE(to)); - for (int i = 0; i < SIZE(from); i++) { + log_assert(GetSize(from) == GetSize(to)); + for (int i = 0; i < GetSize(from); i++) { bitDef_t bit_from(from[i]), bit_to(to[i]); if (bit_from.first != NULL && bit_to.first != NULL && bits.count(bit_from) > 0) bits.insert(bit_to); @@ -346,9 +346,9 @@ struct SigMap void add(RTLIL::SigSpec from, RTLIL::SigSpec to) { - log_assert(SIZE(from) == SIZE(to)); + log_assert(GetSize(from) == GetSize(to)); - for (int i = 0; i < SIZE(from); i++) + for (int i = 0; i < GetSize(from); i++) { RTLIL::SigBit &bf = from[i]; RTLIL::SigBit &bt = to[i]; diff --git a/kernel/utils.h b/kernel/utils.h index 264558b83..1779a9afc 100644 --- a/kernel/utils.h +++ b/kernel/utils.h @@ -83,7 +83,7 @@ public: void reset(const Key &k) { - for (int i = SIZE(backup_state)-1; i >= 0; i--) + for (int i = GetSize(backup_state)-1; i >= 0; i--) if (backup_state[i].count(k) != 0) { if (backup_state[i].at(k) == nullptr) current_state.erase(k); @@ -160,7 +160,7 @@ struct TopoSort found_loops = true; if (analyze_loops) { std::set loop; - for (int i = SIZE(active_stack)-1; i >= 0; i--) { + for (int i = GetSize(active_stack)-1; i >= 0; i--) { loop.insert(active_stack[i]); if (active_stack[i] == n) break; @@ -204,7 +204,7 @@ struct TopoSort for (auto &it : database) sort_worker(it.first, marked_cells, active_cells, active_stack); - log_assert(SIZE(sorted) == SIZE(database)); + log_assert(GetSize(sorted) == GetSize(database)); return !found_loops; } }; diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 0ecb4cdaf..971da78ab 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -66,7 +66,7 @@ std::string vstringf(const char *fmt, va_list ap) return string; } -int SIZE(RTLIL::Wire *wire) +int GetSize(RTLIL::Wire *wire) { return wire->width; } @@ -275,15 +275,15 @@ static void handle_label(std::string &command, bool &from_to_active, const std:: int pos = 0; std::string label; - while (pos < SIZE(command) && (command[pos] == ' ' || command[pos] == '\t')) + while (pos < GetSize(command) && (command[pos] == ' ' || command[pos] == '\t')) pos++; - while (pos < SIZE(command) && command[pos] != ' ' && command[pos] != '\t' && command[pos] != '\r' && command[pos] != '\n') + while (pos < GetSize(command) && command[pos] != ' ' && command[pos] != '\t' && command[pos] != '\r' && command[pos] != '\n') label += command[pos++]; - if (label.back() == ':' && SIZE(label) > 1) + if (label.back() == ':' && GetSize(label) > 1) { - label = label.substr(0, SIZE(label)-1); + label = label.substr(0, GetSize(label)-1); command = command.substr(pos); if (label == run_from) diff --git a/kernel/yosys.h b/kernel/yosys.h index e796919f2..c5da9f046 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -84,8 +84,8 @@ namespace RTLIL { std::string stringf(const char *fmt, ...); std::string vstringf(const char *fmt, va_list ap); -template int SIZE(const T &obj) { return obj.size(); } -int SIZE(RTLIL::Wire *wire); +template int GetSize(const T &obj) { return obj.size(); } +int GetSize(RTLIL::Wire *wire); YOSYS_NAMESPACE_END diff --git a/manual/CHAPTER_Prog/stubnets.cc b/manual/CHAPTER_Prog/stubnets.cc index ef4b1245d..8880af5a6 100644 --- a/manual/CHAPTER_Prog/stubnets.cc +++ b/manual/CHAPTER_Prog/stubnets.cc @@ -62,7 +62,7 @@ static void find_stub_nets(RTLIL::Design *design, RTLIL::Module *module, bool re // for each bit (unless it is a constant): // check if it is used at least two times and add to stub_bits otherwise - for (int i = 0; i < SIZE(sig); i++) + for (int i = 0; i < GetSize(sig); i++) if (sig[i].wire != NULL && (bit_usage_count[sig[i]] + usage_offset) < 2) stub_bits.insert(i); @@ -72,7 +72,7 @@ static void find_stub_nets(RTLIL::Design *design, RTLIL::Module *module, bool re // report stub bits and/or stub wires, don't report single bits // if called with report_bits set to false. - if (SIZE(stub_bits) == SIZE(sig)) { + if (GetSize(stub_bits) == GetSize(sig)) { log(" found stub wire: %s\n", RTLIL::id2cstr(wire->name)); } else { if (!report_bits) diff --git a/manual/PRESENTATION_Prog/my_cmd.cc b/manual/PRESENTATION_Prog/my_cmd.cc index 381b05871..3e3cf13a0 100644 --- a/manual/PRESENTATION_Prog/my_cmd.cc +++ b/manual/PRESENTATION_Prog/my_cmd.cc @@ -12,7 +12,7 @@ struct MyPass : public Pass { log("Modules in current design:\n"); for (auto mod : design->modules()) log(" %s (%zd wires, %zd cells)\n", log_id(mod), - SIZE(mod->wires()), SIZE(mod->cells())); + GetSize(mod->wires()), GetSize(mod->cells())); } } MyPass; diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc index 4e8234d16..da597ac45 100644 --- a/passes/cmds/plugin.cc +++ b/passes/cmds/plugin.cc @@ -112,7 +112,7 @@ struct PluginPass : public Pass { log("\n"); int max_alias_len = 1; for (auto &it : loaded_plugin_aliases) - max_alias_len = std::max(max_alias_len, SIZE(it.first)); + max_alias_len = std::max(max_alias_len, GetSize(it.first)); for (auto &it : loaded_plugin_aliases) log("Alias: %-*s %s\n", max_alias_len, it.first.c_str(), it.second.c_str()); } diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index 05da47923..abe6cd460 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -178,7 +178,7 @@ struct ShowWorker std::string gen_signode_simple(RTLIL::SigSpec sig, bool range_check = true) { - if (SIZE(sig) == 0) { + if (GetSize(sig) == 0) { fprintf(f, "v%d [ label=\"\" ];\n", single_idx_count); return stringf("v%d", single_idx_count++); } diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 51f1f0ca1..d68c57b20 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -107,15 +107,15 @@ struct statdata_t "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", "$add", "$sub", "$mul", "$div", "$mod", "$pow")) { - int width_a = it.second->hasPort("\\A") ? SIZE(it.second->getPort("\\A")) : 0; - int width_b = it.second->hasPort("\\B") ? SIZE(it.second->getPort("\\B")) : 0; - int width_y = it.second->hasPort("\\Y") ? SIZE(it.second->getPort("\\Y")) : 0; + int width_a = it.second->hasPort("\\A") ? GetSize(it.second->getPort("\\A")) : 0; + int width_b = it.second->hasPort("\\B") ? GetSize(it.second->getPort("\\B")) : 0; + int width_y = it.second->hasPort("\\Y") ? GetSize(it.second->getPort("\\Y")) : 0; cell_type = stringf("%s_%d", cell_type.c_str(), std::max({width_a, width_b, width_y})); } else if (cell_type.in("$mux", "$pmux")) - cell_type = stringf("%s_%d", cell_type.c_str(), SIZE(it.second->getPort("\\Y"))); + cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(it.second->getPort("\\Y"))); else if (cell_type.in("$sr", "$dff", "$dffsr", "$adff", "$dlatch", "$dlatchsr")) - cell_type = stringf("%s_%d", cell_type.c_str(), SIZE(it.second->getPort("\\Q"))); + cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(it.second->getPort("\\Q"))); } num_cells++; diff --git a/passes/fsm/fsm_extract.cc b/passes/fsm/fsm_extract.cc index f3369758e..e01c54969 100644 --- a/passes/fsm/fsm_extract.cc +++ b/passes/fsm/fsm_extract.cc @@ -73,9 +73,9 @@ static bool find_states(RTLIL::SigSpec sig, const RTLIL::SigSpec &dff_out, RTLIL sig_aa.replace(sig_y, sig_a); RTLIL::SigSpec sig_bb; - for (int i = 0; i < SIZE(sig_b)/SIZE(sig_a); i++) { + for (int i = 0; i < GetSize(sig_b)/GetSize(sig_a); i++) { RTLIL::SigSpec s = sig; - s.replace(sig_y, sig_b.extract(i*SIZE(sig_a), SIZE(sig_a))); + s.replace(sig_y, sig_b.extract(i*GetSize(sig_a), GetSize(sig_a))); sig_bb.append(s); } @@ -98,8 +98,8 @@ static bool find_states(RTLIL::SigSpec sig, const RTLIL::SigSpec &dff_out, RTLIL if (!find_states(sig_aa, dff_out, ctrl, states)) return false; - for (int i = 0; i < SIZE(sig_bb)/SIZE(sig_aa); i++) { - if (!find_states(sig_bb.extract(i*SIZE(sig_aa), SIZE(sig_aa)), dff_out, ctrl, states)) + for (int i = 0; i < GetSize(sig_bb)/GetSize(sig_aa); i++) { + if (!find_states(sig_bb.extract(i*GetSize(sig_aa), GetSize(sig_aa)), dff_out, ctrl, states)) return false; } } @@ -110,7 +110,7 @@ static bool find_states(RTLIL::SigSpec sig, const RTLIL::SigSpec &dff_out, RTLIL static RTLIL::Const sig2const(ConstEval &ce, RTLIL::SigSpec sig, RTLIL::State noconst_state, RTLIL::SigSpec dont_care = RTLIL::SigSpec()) { if (dont_care.size() > 0) { - for (int i = 0; i < SIZE(sig); i++) + for (int i = 0; i < GetSize(sig); i++) if (dont_care.extract(sig[i]).size() > 0) sig[i] = noconst_state; } @@ -118,7 +118,7 @@ static RTLIL::Const sig2const(ConstEval &ce, RTLIL::SigSpec sig, RTLIL::State no ce.assign_map.apply(sig); ce.values_map.apply(sig); - for (int i = 0; i < SIZE(sig); i++) + for (int i = 0; i < GetSize(sig); i++) if (sig[i].wire != NULL) sig[i] = noconst_state; @@ -148,7 +148,7 @@ undef_bit_in_next_state: tr.ctrl_out = sig2const(ce, ctrl_out, RTLIL::State::Sx); std::map ctrl_in_bit_indices; - for (int i = 0; i < SIZE(ctrl_in); i++) + for (int i = 0; i < GetSize(ctrl_in); i++) ctrl_in_bit_indices[ctrl_in[i]] = i; for (auto &it : ctrl_in_bit_indices) @@ -290,7 +290,7 @@ static void extract_fsm(RTLIL::Wire *wire) log(" fsm extraction failed: state selection tree is not closed.\n"); return; } - if (SIZE(states) <= 1) { + if (GetSize(states) <= 1) { log(" fsm extraction failed: at least two states are required.\n"); return; } diff --git a/passes/fsm/fsm_map.cc b/passes/fsm/fsm_map.cc index 2f6ac8543..a260653fb 100644 --- a/passes/fsm/fsm_map.cc +++ b/passes/fsm/fsm_map.cc @@ -30,8 +30,8 @@ PRIVATE_NAMESPACE_BEGIN static bool pattern_is_subset(const RTLIL::Const &super_pattern, const RTLIL::Const &sub_pattern) { - log_assert(SIZE(super_pattern.bits) == SIZE(sub_pattern.bits)); - for (int i = 0; i < SIZE(super_pattern.bits); i++) + log_assert(GetSize(super_pattern.bits) == GetSize(sub_pattern.bits)); + for (int i = 0; i < GetSize(super_pattern.bits); i++) if (sub_pattern.bits[i] == RTLIL::State::S0 || sub_pattern.bits[i] == RTLIL::State::S1) { if (super_pattern.bits[i] == RTLIL::State::S0 || super_pattern.bits[i] == RTLIL::State::S1) { if (super_pattern.bits[i] != sub_pattern.bits[i]) @@ -91,7 +91,7 @@ static void implement_pattern_cache(RTLIL::Module *module, std::mapconnect(next_state_wire, fsm_data.state_table.front()); } diff --git a/passes/fsm/fsm_opt.cc b/passes/fsm/fsm_opt.cc index 805e3925b..6685e8e0e 100644 --- a/passes/fsm/fsm_opt.cc +++ b/passes/fsm/fsm_opt.cc @@ -43,7 +43,7 @@ struct FsmOpt std::vector new_state_table; std::map old_to_new_state; - for (int i = 0; i < SIZE(fsm_data.state_table); i++) + for (int i = 0; i < GetSize(fsm_data.state_table); i++) if (i != fsm_data.reset_state) unreachable_states.insert(i); @@ -53,12 +53,12 @@ struct FsmOpt if (unreachable_states.empty()) break; - for (int i = 0; i < SIZE(fsm_data.state_table); i++) { + for (int i = 0; i < GetSize(fsm_data.state_table); i++) { if (unreachable_states.count(i)) { log(" Removing unreachable state %s.\n", log_signal(fsm_data.state_table[i])); continue; } - old_to_new_state[i] = SIZE(new_state_table); + old_to_new_state[i] = GetSize(new_state_table); new_state_table.push_back(fsm_data.state_table[i]); } diff --git a/passes/fsm/fsm_recode.cc b/passes/fsm/fsm_recode.cc index 640bed1e5..2b9a26d44 100644 --- a/passes/fsm/fsm_recode.cc +++ b/passes/fsm/fsm_recode.cc @@ -77,7 +77,7 @@ static void fsm_recode(RTLIL::Cell *cell, RTLIL::Module *module, FILE *fm_set_fs if (!default_encoding.empty()) encoding = default_encoding; else - encoding = SIZE(fsm_data.state_table) < 32 ? "one-hot" : "binary"; + encoding = GetSize(fsm_data.state_table) < 32 ? "one-hot" : "binary"; log(" mapping auto encoding to `%s` for this FSM.\n", encoding.c_str()); } diff --git a/passes/fsm/fsmdata.h b/passes/fsm/fsmdata.h index 17d22c86e..5671d0006 100644 --- a/passes/fsm/fsmdata.h +++ b/passes/fsm/fsmdata.h @@ -143,24 +143,24 @@ struct FsmData log("\n"); log(" Input signals:\n"); RTLIL::SigSpec sig_in = cell->getPort("\\CTRL_IN"); - for (int i = 0; i < SIZE(sig_in); i++) + for (int i = 0; i < GetSize(sig_in); i++) log(" %3d: %s\n", i, log_signal(sig_in[i])); log("\n"); log(" Output signals:\n"); RTLIL::SigSpec sig_out = cell->getPort("\\CTRL_OUT"); - for (int i = 0; i < SIZE(sig_out); i++) + for (int i = 0; i < GetSize(sig_out); i++) log(" %3d: %s\n", i, log_signal(sig_out[i])); log("\n"); log(" State encoding:\n"); - for (int i = 0; i < SIZE(state_table); i++) + for (int i = 0; i < GetSize(state_table); i++) log(" %3d: %10s%s\n", i, log_signal(state_table[i], false), int(i) == reset_state ? " " : ""); log("\n"); log(" Transition Table (state_in, ctrl_in, state_out, ctrl_out):\n"); - for (int i = 0; i < SIZE(transition_table); i++) { + for (int i = 0; i < GetSize(transition_table); i++) { transition_t &tr = transition_table[i]; log(" %5d: %5d %s -> %5d %s\n", i, tr.state_in, log_signal(tr.ctrl_in), tr.state_out, log_signal(tr.ctrl_out)); } diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc index 449604c1a..4fb10a989 100644 --- a/passes/memory/memory_map.cc +++ b/passes/memory/memory_map.cc @@ -58,21 +58,21 @@ struct MemoryMapWorker RTLIL::Wire *addr_decode(RTLIL::SigSpec addr_sig, RTLIL::SigSpec addr_val) { std::pair key(addr_sig, addr_val); - log_assert(SIZE(addr_sig) == SIZE(addr_val)); + log_assert(GetSize(addr_sig) == GetSize(addr_val)); if (decoder_cache.count(key) == 0) { - if (SIZE(addr_sig) < 2) { + if (GetSize(addr_sig) < 2) { decoder_cache[key] = module->Eq(NEW_ID, addr_sig, addr_val); } else { - int split_at = SIZE(addr_sig) / 2; + int split_at = GetSize(addr_sig) / 2; RTLIL::SigBit left_eq = addr_decode(addr_sig.extract(0, split_at), addr_val.extract(0, split_at)); - RTLIL::SigBit right_eq = addr_decode(addr_sig.extract(split_at, SIZE(addr_sig) - split_at), addr_val.extract(split_at, SIZE(addr_val) - split_at)); + RTLIL::SigBit right_eq = addr_decode(addr_sig.extract(split_at, GetSize(addr_sig) - split_at), addr_val.extract(split_at, GetSize(addr_val) - split_at)); decoder_cache[key] = module->And(NEW_ID, left_eq, right_eq); } } RTLIL::SigBit bit = decoder_cache.at(key); - log_assert(bit.wire != nullptr && SIZE(bit.wire) == 1); + log_assert(bit.wire != nullptr && GetSize(bit.wire) == 1); return bit.wire; } diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 004a2078a..c0b8853a6 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -229,9 +229,9 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (!used_signals.check_any(s2) && wire->port_id == 0 && !wire->get_bool_attribute("\\keep")) { maybe_del_wires.push_back(wire); } else { - log_assert(SIZE(s1) == SIZE(s2)); + log_assert(GetSize(s1) == GetSize(s2)); RTLIL::SigSig new_conn; - for (int i = 0; i < SIZE(s1); i++) + for (int i = 0; i < GetSize(s1); i++) if (s1[i] != s2[i]) { new_conn.first.append_bit(s1[i]); new_conn.second.append_bit(s2[i]); @@ -250,7 +250,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos RTLIL::SigSpec sig = assign_map(RTLIL::SigSpec(wire)); if (!used_signals_nodrivers.check_any(sig)) { std::string unused_bits; - for (int i = 0; i < SIZE(sig); i++) { + for (int i = 0; i < GetSize(sig); i++) { if (sig[i].wire == NULL) continue; if (!used_signals_nodrivers.check(sig[i])) { @@ -299,7 +299,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose) bool is_signed = cell->type == "$pos" && cell->getParam("\\A_SIGNED").as_bool(); RTLIL::SigSpec a = cell->getPort("\\A"); RTLIL::SigSpec y = cell->getPort("\\Y"); - a.extend_u0(SIZE(y), is_signed); + a.extend_u0(GetSize(y), is_signed); module->connect(y, a); delcells.push_back(cell); } diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc index 7c9fca961..c726c7b3d 100644 --- a/passes/opt/opt_const.cc +++ b/passes/opt/opt_const.cc @@ -107,7 +107,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ enum { GRP_DYN, GRP_CONST_A, GRP_CONST_B, GRP_CONST_AB, GRP_N }; std::map, std::set> grouped_bits[GRP_N]; - for (int i = 0; i < SIZE(bits_y); i++) + for (int i = 0; i < GetSize(bits_y); i++) { int group_idx = GRP_DYN; RTLIL::SigBit bit_a = bits_a[i], bit_b = bits_b[i]; @@ -131,7 +131,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ } for (int i = 0; i < GRP_N; i++) - if (SIZE(grouped_bits[i]) == SIZE(bits_y)) + if (GetSize(grouped_bits[i]) == GetSize(bits_y)) return false; log("Replacing %s cell `%s' in module `%s' with cells using grouped bits:\n", @@ -142,7 +142,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ if (grouped_bits[i].empty()) continue; - RTLIL::Wire *new_y = module->addWire(NEW_ID, SIZE(grouped_bits[i])); + RTLIL::Wire *new_y = module->addWire(NEW_ID, GetSize(grouped_bits[i])); RTLIL::SigSpec new_a, new_b; RTLIL::SigSig new_conn; @@ -486,8 +486,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons RTLIL::SigSpec new_a, new_b; - log_assert(SIZE(a) == SIZE(b)); - for (int i = 0; i < SIZE(a); i++) { + log_assert(GetSize(a) == GetSize(b)); + for (int i = 0; i < GetSize(a); i++) { if (a[i].wire == NULL && b[i].wire == NULL && a[i] != b[i] && a[i].data <= RTLIL::State::S1 && b[i].data <= RTLIL::State::S1) { cover_list("opt.opt_const.eqneq.isneq", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); RTLIL::SigSpec new_y = RTLIL::SigSpec((cell->type == "$eq" || cell->type == "$eqx") ? RTLIL::State::S0 : RTLIL::State::S1); @@ -559,15 +559,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); RTLIL::SigSpec sig_y(cell->type == "$shiftx" ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam("\\Y_WIDTH").as_int()); - if (SIZE(sig_a) < SIZE(sig_y)) - sig_a.extend(SIZE(sig_y), cell->getParam("\\A_SIGNED").as_bool()); + if (GetSize(sig_a) < GetSize(sig_y)) + sig_a.extend(GetSize(sig_y), cell->getParam("\\A_SIGNED").as_bool()); - for (int i = 0; i < SIZE(sig_y); i++) { + for (int i = 0; i < GetSize(sig_y); i++) { int idx = i + shift_bits; - if (0 <= idx && idx < SIZE(sig_a)) + if (0 <= idx && idx < GetSize(sig_a)) sig_y[i] = sig_a[idx]; - else if (SIZE(sig_a) <= idx && sign_ext) - sig_y[i] = sig_a[SIZE(sig_a)-1]; + else if (GetSize(sig_a) <= idx && sign_ext) + sig_y[i] = sig_a[GetSize(sig_a)-1]; } cover_list("opt.opt_const.constshift", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", cell->type.str()); @@ -754,7 +754,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->getPort("\\S").size() != new_s.size()) { cover_list("opt.opt_const.mux_reduce", "$mux", "$pmux", cell->type.str()); log("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n", - SIZE(cell->getPort("\\S")) - SIZE(new_s), log_id(cell->type), log_id(cell), log_id(module)); + GetSize(cell->getPort("\\S")) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module)); cell->setPort("\\A", new_a); cell->setPort("\\B", new_b); cell->setPort("\\S", new_s); @@ -900,11 +900,11 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons std::vector new_b = RTLIL::SigSpec(i, 6); - while (SIZE(new_b) > 1 && new_b.back() == RTLIL::State::S0) + while (GetSize(new_b) > 1 && new_b.back() == RTLIL::State::S0) new_b.pop_back(); cell->type = "$shl"; - cell->parameters["\\B_WIDTH"] = SIZE(new_b); + cell->parameters["\\B_WIDTH"] = GetSize(new_b); cell->parameters["\\B_SIGNED"] = false; cell->setPort("\\B", new_b); cell->check(); diff --git a/passes/opt/share.cc b/passes/opt/share.cc index 44374482f..354586937 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -109,14 +109,14 @@ struct ShareWorker static int bits_macc_port(const Macc::port_t &p, int width) { - if (SIZE(p.in_a) == 0 || SIZE(p.in_b) == 0) - return std::min(std::max(SIZE(p.in_a), SIZE(p.in_b)), width); - return std::min(SIZE(p.in_a), width) * std::min(SIZE(p.in_b), width) / 2; + if (GetSize(p.in_a) == 0 || GetSize(p.in_b) == 0) + return std::min(std::max(GetSize(p.in_a), GetSize(p.in_b)), width); + return std::min(GetSize(p.in_a), width) * std::min(GetSize(p.in_b), width) / 2; } static int bits_macc(const Macc &m, int width) { - int bits = SIZE(m.bit_ports); + int bits = GetSize(m.bit_ports); for (auto &p : m.ports) bits += bits_macc_port(p, width); return bits; @@ -125,17 +125,17 @@ struct ShareWorker static int bits_macc(RTLIL::Cell *c) { Macc m(c); - int width = SIZE(c->getPort("\\Y")); + int width = GetSize(c->getPort("\\Y")); return bits_macc(m, width); } static bool cmp_macc_ports(const Macc::port_t &p1, const Macc::port_t &p2) { - bool mul1 = SIZE(p1.in_a) && SIZE(p1.in_b); - bool mul2 = SIZE(p2.in_a) && SIZE(p2.in_b); + bool mul1 = GetSize(p1.in_a) && GetSize(p1.in_b); + bool mul2 = GetSize(p2.in_a) && GetSize(p2.in_b); - int w1 = mul1 ? SIZE(p1.in_a) * SIZE(p1.in_b) : SIZE(p1.in_a) + SIZE(p1.in_b); - int w2 = mul2 ? SIZE(p2.in_a) * SIZE(p2.in_b) : SIZE(p2.in_a) + SIZE(p2.in_b); + int w1 = mul1 ? GetSize(p1.in_a) * GetSize(p1.in_b) : GetSize(p1.in_a) + GetSize(p1.in_b); + int w2 = mul2 ? GetSize(p2.in_a) * GetSize(p2.in_b) : GetSize(p2.in_a) + GetSize(p2.in_b); if (mul1 != mul2) return mul1; @@ -164,22 +164,22 @@ struct ShareWorker if (p1.do_subtract != p2.do_subtract) return -1; - bool mul1 = SIZE(p1.in_a) && SIZE(p1.in_b); - bool mul2 = SIZE(p2.in_a) && SIZE(p2.in_b); + bool mul1 = GetSize(p1.in_a) && GetSize(p1.in_b); + bool mul2 = GetSize(p2.in_a) && GetSize(p2.in_b); if (mul1 != mul2) return -1; bool force_signed = false, force_not_signed = false; - if ((SIZE(p1.in_a) && SIZE(p1.in_a) < w1) || (SIZE(p1.in_b) && SIZE(p1.in_b) < w1)) { + if ((GetSize(p1.in_a) && GetSize(p1.in_a) < w1) || (GetSize(p1.in_b) && GetSize(p1.in_b) < w1)) { if (p1.is_signed) force_signed = true; else force_not_signed = true; } - if ((SIZE(p2.in_a) && SIZE(p2.in_a) < w2) || (SIZE(p2.in_b) && SIZE(p2.in_b) < w2)) { + if ((GetSize(p2.in_a) && GetSize(p2.in_a) < w2) || (GetSize(p2.in_b) && GetSize(p2.in_b) < w2)) { if (p2.is_signed) force_signed = true; else @@ -194,22 +194,22 @@ struct ShareWorker RTLIL::SigSpec sig_a1 = p1.in_a, sig_b1 = p1.in_b; RTLIL::SigSpec sig_a2 = p2.in_a, sig_b2 = p2.in_b; - RTLIL::SigSpec sig_a = SIZE(sig_a1) > SIZE(sig_a2) ? sig_a1 : sig_a2; - RTLIL::SigSpec sig_b = SIZE(sig_b1) > SIZE(sig_b2) ? sig_b1 : sig_b2; + RTLIL::SigSpec sig_a = GetSize(sig_a1) > GetSize(sig_a2) ? sig_a1 : sig_a2; + RTLIL::SigSpec sig_b = GetSize(sig_b1) > GetSize(sig_b2) ? sig_b1 : sig_b2; - sig_a1.extend_u0(SIZE(sig_a), p1.is_signed); - sig_b1.extend_u0(SIZE(sig_b), p1.is_signed); + sig_a1.extend_u0(GetSize(sig_a), p1.is_signed); + sig_b1.extend_u0(GetSize(sig_b), p1.is_signed); - sig_a2.extend_u0(SIZE(sig_a), p2.is_signed); - sig_b2.extend_u0(SIZE(sig_b), p2.is_signed); + sig_a2.extend_u0(GetSize(sig_a), p2.is_signed); + sig_b2.extend_u0(GetSize(sig_b), p2.is_signed); - if (supercell_aux && SIZE(sig_a)) { - sig_a = module->addWire(NEW_ID, SIZE(sig_a)); + if (supercell_aux && GetSize(sig_a)) { + sig_a = module->addWire(NEW_ID, GetSize(sig_a)); supercell_aux->insert(module->addMux(NEW_ID, sig_a2, sig_a1, act, sig_a)); } - if (supercell_aux && SIZE(sig_b)) { - sig_b = module->addWire(NEW_ID, SIZE(sig_b)); + if (supercell_aux && GetSize(sig_b)) { + sig_b = module->addWire(NEW_ID, GetSize(sig_b)); supercell_aux->insert(module->addMux(NEW_ID, sig_b2, sig_b1, act, sig_b)); } @@ -221,13 +221,13 @@ struct ShareWorker supermacc->ports.push_back(p); } - int score = 1000 + abs(SIZE(p1.in_a) - SIZE(p2.in_a)) * std::max(abs(SIZE(p1.in_b) - SIZE(p2.in_b)), 1); + int score = 1000 + abs(GetSize(p1.in_a) - GetSize(p2.in_a)) * std::max(abs(GetSize(p1.in_b) - GetSize(p2.in_b)), 1); - for (int i = 0; i < std::min(SIZE(p1.in_a), SIZE(p2.in_a)); i++) + for (int i = 0; i < std::min(GetSize(p1.in_a), GetSize(p2.in_a)); i++) if (p1.in_a[i] == p2.in_a[i] && score > 0) score--; - for (int i = 0; i < std::min(SIZE(p1.in_b), SIZE(p2.in_b)); i++) + for (int i = 0; i < std::min(GetSize(p1.in_b), GetSize(p2.in_b)); i++) if (p1.in_b[i] == p2.in_b[i] && score > 0) score--; @@ -239,7 +239,7 @@ struct ShareWorker { Macc m1(c1), m2(c2), supermacc; - int w1 = SIZE(c1->getPort("\\Y")), w2 = SIZE(c2->getPort("\\Y")); + int w1 = GetSize(c1->getPort("\\Y")), w2 = GetSize(c2->getPort("\\Y")); int width = std::max(w1, w2); m1.optimize(w1); @@ -250,10 +250,10 @@ struct ShareWorker std::set m1_unmapped, m2_unmapped; - for (int i = 0; i < SIZE(m1.ports); i++) + for (int i = 0; i < GetSize(m1.ports); i++) m1_unmapped.insert(i); - for (int i = 0; i < SIZE(m2.ports); i++) + for (int i = 0; i < GetSize(m2.ports); i++) m2_unmapped.insert(i); while (1) @@ -280,14 +280,14 @@ struct ShareWorker RTLIL::SigSpec sig_a = m1.ports[i].in_a; RTLIL::SigSpec sig_b = m1.ports[i].in_b; - if (supercell_aux && SIZE(sig_a)) { - sig_a = module->addWire(NEW_ID, SIZE(sig_a)); - supercell_aux->insert(module->addMux(NEW_ID, RTLIL::SigSpec(0, SIZE(sig_a)), m1.ports[i].in_a, act, sig_a)); + if (supercell_aux && GetSize(sig_a)) { + sig_a = module->addWire(NEW_ID, GetSize(sig_a)); + supercell_aux->insert(module->addMux(NEW_ID, RTLIL::SigSpec(0, GetSize(sig_a)), m1.ports[i].in_a, act, sig_a)); } - if (supercell_aux && SIZE(sig_b)) { - sig_b = module->addWire(NEW_ID, SIZE(sig_b)); - supercell_aux->insert(module->addMux(NEW_ID, RTLIL::SigSpec(0, SIZE(sig_b)), m1.ports[i].in_b, act, sig_b)); + if (supercell_aux && GetSize(sig_b)) { + sig_b = module->addWire(NEW_ID, GetSize(sig_b)); + supercell_aux->insert(module->addMux(NEW_ID, RTLIL::SigSpec(0, GetSize(sig_b)), m1.ports[i].in_b, act, sig_b)); } Macc::port_t p; @@ -303,14 +303,14 @@ struct ShareWorker RTLIL::SigSpec sig_a = m2.ports[i].in_a; RTLIL::SigSpec sig_b = m2.ports[i].in_b; - if (supercell_aux && SIZE(sig_a)) { - sig_a = module->addWire(NEW_ID, SIZE(sig_a)); - supercell_aux->insert(module->addMux(NEW_ID, m2.ports[i].in_a, RTLIL::SigSpec(0, SIZE(sig_a)), act, sig_a)); + if (supercell_aux && GetSize(sig_a)) { + sig_a = module->addWire(NEW_ID, GetSize(sig_a)); + supercell_aux->insert(module->addMux(NEW_ID, m2.ports[i].in_a, RTLIL::SigSpec(0, GetSize(sig_a)), act, sig_a)); } - if (supercell_aux && SIZE(sig_b)) { - sig_b = module->addWire(NEW_ID, SIZE(sig_b)); - supercell_aux->insert(module->addMux(NEW_ID, m2.ports[i].in_b, RTLIL::SigSpec(0, SIZE(sig_b)), act, sig_b)); + if (supercell_aux && GetSize(sig_b)) { + sig_b = module->addWire(NEW_ID, GetSize(sig_b)); + supercell_aux->insert(module->addMux(NEW_ID, m2.ports[i].in_b, RTLIL::SigSpec(0, GetSize(sig_b)), act, sig_b)); } Macc::port_t p; @@ -765,7 +765,7 @@ struct ShareWorker std::map p_bits; std::vector p_first_bits = p.first; - for (int i = 0; i < SIZE(p_first_bits); i++) { + for (int i = 0; i < GetSize(p_first_bits); i++) { RTLIL::SigBit b = p_first_bits[i]; RTLIL::State v = p.second.bits[i]; if (p_bits.count(b) && p_bits.at(b) != v) @@ -837,13 +837,13 @@ struct ShareWorker if (cell_out_bits.count(bit)) used_in_a = true; - for (int i = 0; i < SIZE(sig_b); i++) + for (int i = 0; i < GetSize(sig_b); i++) if (cell_out_bits.count(sig_b[i])) used_in_b_parts.insert(i / width); if (used_in_a) for (auto p : c_patterns) { - for (int i = 0; i < SIZE(sig_s); i++) + for (int i = 0; i < GetSize(sig_s); i++) p.first.append_bit(sig_s[i]), p.second.bits.push_back(RTLIL::State::S0); if (sort_check_activation_pattern(p)) activation_patterns_cache[cell].insert(p); @@ -899,7 +899,7 @@ struct ShareWorker std::vector p_first = p.first; std::pair new_p; - for (int i = 0; i < SIZE(p_first); i++) + for (int i = 0; i < GetSize(p_first); i++) if (filter_bits.count(p_first[i]) == 0) { new_p.first.append_bit(p_first[i]); new_p.second.bits.push_back(p.second.bits.at(i)); @@ -1078,7 +1078,7 @@ struct ShareWorker return; log("Found %d cells in module %s that may be considered for resource sharing.\n", - SIZE(shareable_cells), log_id(module)); + GetSize(shareable_cells), log_id(module)); for (auto cell : module->cells()) if (cell->type == "$pmux") @@ -1108,7 +1108,7 @@ struct ShareWorker continue; } - log(" Found %d activation_patterns using ctrl signal %s.\n", SIZE(cell_activation_patterns), log_signal(cell_activation_signals)); + log(" Found %d activation_patterns using ctrl signal %s.\n", GetSize(cell_activation_patterns), log_signal(cell_activation_signals)); std::vector candidates; find_shareable_partners(candidates, cell); @@ -1118,7 +1118,7 @@ struct ShareWorker continue; } - log(" Found %d candidates:", SIZE(candidates)); + log(" Found %d candidates:", GetSize(candidates)); for (auto c : candidates) log(" %s", log_id(c)); log("\n"); @@ -1144,7 +1144,7 @@ struct ShareWorker } log(" Found %d activation_patterns using ctrl signal %s.\n", - SIZE(other_cell_activation_patterns), log_signal(other_cell_activation_signals)); + GetSize(other_cell_activation_patterns), log_signal(other_cell_activation_signals)); const std::set &cell_forbidden_controls = find_forbidden_controls(cell); const std::set &other_cell_forbidden_controls = find_forbidden_controls(other_cell); @@ -1240,12 +1240,12 @@ struct ShareWorker ez.assume(ez.AND(ez.expression(ez.OpOr, cell_active), ez.expression(ez.OpOr, other_cell_active))); log(" Size of SAT problem: %d cells, %d variables, %d clauses\n", - SIZE(sat_cells), ez.numCnfVariables(), ez.numCnfClauses()); + GetSize(sat_cells), ez.numCnfVariables(), ez.numCnfClauses()); if (ez.solve(sat_model, sat_model_values)) { log(" According to the SAT solver this pair of cells can not be shared.\n"); - log(" Model from SAT solver: %s = %d'", log_signal(all_ctrl_signals), SIZE(sat_model_values)); - for (int i = SIZE(sat_model_values)-1; i >= 0; i--) + log(" Model from SAT solver: %s = %d'", log_signal(all_ctrl_signals), GetSize(sat_model_values)); + for (int i = GetSize(sat_model_values)-1; i >= 0; i--) log("%c", sat_model_values[i] ? '1' : '0'); log("\n"); continue; @@ -1331,7 +1331,7 @@ struct ShareWorker } if (!cells_to_remove.empty()) { - log("Removing %d cells in module %s:\n", SIZE(cells_to_remove), log_id(module)); + log("Removing %d cells in module %s:\n", GetSize(cells_to_remove), log_id(module)); for (auto c : cells_to_remove) { log(" Removing cell %s (%s).\n", log_id(c), log_id(c->type)); module->remove(c); diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 58a6d1b0d..89b1f8856 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -65,20 +65,20 @@ struct WreduceWorker SigSpec sig_y = mi.sigmap(cell->getPort("\\Y")); std::vector bits_removed; - for (int i = SIZE(sig_y)-1; i >= 0; i--) + for (int i = GetSize(sig_y)-1; i >= 0; i--) { auto info = mi.query(sig_y[i]); - if (!info->is_output && SIZE(info->ports) <= 1) { + if (!info->is_output && GetSize(info->ports) <= 1) { bits_removed.push_back(Sx); continue; } SigBit ref = sig_a[i]; - for (int k = 0; k < SIZE(sig_s); k++) { - if (ref != Sx && sig_b[k*SIZE(sig_a) + i] != Sx && ref != sig_b[k*SIZE(sig_a) + i]) + for (int k = 0; k < GetSize(sig_s); k++) { + if (ref != Sx && sig_b[k*GetSize(sig_a) + i] != Sx && ref != sig_b[k*GetSize(sig_a) + i]) goto no_match_ab; - if (sig_b[k*SIZE(sig_a) + i] != Sx) - ref = sig_b[k*SIZE(sig_a) + i]; + if (sig_b[k*GetSize(sig_a) + i] != Sx) + ref = sig_b[k*GetSize(sig_a) + i]; } if (0) no_match_ab: @@ -90,10 +90,10 @@ struct WreduceWorker return; SigSpec sig_removed; - for (int i = SIZE(bits_removed)-1; i >= 0; i--) + for (int i = GetSize(bits_removed)-1; i >= 0; i--) sig_removed.append_bit(bits_removed[i]); - if (SIZE(bits_removed) == SIZE(sig_y)) { + if (GetSize(bits_removed) == GetSize(sig_y)) { log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); module->connect(sig_y, sig_removed); module->remove(cell); @@ -101,10 +101,10 @@ struct WreduceWorker } log("Removed top %d bits (of %d) from mux cell %s.%s (%s).\n", - SIZE(sig_removed), SIZE(sig_y), log_id(module), log_id(cell), log_id(cell->type)); + GetSize(sig_removed), GetSize(sig_y), log_id(module), log_id(cell), log_id(cell->type)); - int n_removed = SIZE(sig_removed); - int n_kept = SIZE(sig_y) - SIZE(sig_removed); + int n_removed = GetSize(sig_removed); + int n_kept = GetSize(sig_y) - GetSize(sig_removed); SigSpec new_work_queue_bits; new_work_queue_bits.append(sig_a.extract(n_kept, n_removed)); @@ -114,9 +114,9 @@ struct WreduceWorker SigSpec new_sig_y = sig_y.extract(0, n_kept); SigSpec new_sig_b; - for (int k = 0; k < SIZE(sig_s); k++) { - new_sig_b.append(sig_b.extract(k*SIZE(sig_a), n_kept)); - new_work_queue_bits.append(sig_b.extract(k*SIZE(sig_a) + n_kept, n_removed)); + for (int k = 0; k < GetSize(sig_s); k++) { + new_sig_b.append(sig_b.extract(k*GetSize(sig_a), n_kept)); + new_work_queue_bits.append(sig_b.extract(k*GetSize(sig_a) + n_kept, n_removed)); } for (auto bit : new_work_queue_bits) @@ -139,24 +139,24 @@ struct WreduceWorker port_signed = false; int bits_removed = 0; - if (SIZE(sig) > max_port_size) { - bits_removed = SIZE(sig) - max_port_size; + if (GetSize(sig) > max_port_size) { + bits_removed = GetSize(sig) - max_port_size; for (auto bit : sig.extract(max_port_size, bits_removed)) work_queue_bits.insert(bit); sig = sig.extract(0, max_port_size); } if (port_signed) { - while (SIZE(sig) > 1 && sig[SIZE(sig)-1] == sig[SIZE(sig)-2]) - work_queue_bits.insert(sig[SIZE(sig)-1]), sig.remove(SIZE(sig)-1), bits_removed++; + while (GetSize(sig) > 1 && sig[GetSize(sig)-1] == sig[GetSize(sig)-2]) + work_queue_bits.insert(sig[GetSize(sig)-1]), sig.remove(GetSize(sig)-1), bits_removed++; } else { - while (SIZE(sig) > 1 && sig[SIZE(sig)-1] == S0) - work_queue_bits.insert(sig[SIZE(sig)-1]), sig.remove(SIZE(sig)-1), bits_removed++; + while (GetSize(sig) > 1 && sig[GetSize(sig)-1] == S0) + work_queue_bits.insert(sig[GetSize(sig)-1]), sig.remove(GetSize(sig)-1), bits_removed++; } if (bits_removed) { log("Removed top %d bits (of %d) from port %c of cell %s.%s (%s).\n", - bits_removed, SIZE(sig) + bits_removed, port, log_id(module), log_id(cell), log_id(cell->type)); + bits_removed, GetSize(sig) + bits_removed, port, log_id(module), log_id(cell), log_id(cell->type)); cell->setPort(stringf("\\%c", port), sig); did_something = true; } @@ -175,12 +175,12 @@ struct WreduceWorker // Reduce size of ports A and B based on constant input bits and size of output port - int max_port_a_size = cell->hasPort("\\A") ? SIZE(cell->getPort("\\A")) : -1; - int max_port_b_size = cell->hasPort("\\B") ? SIZE(cell->getPort("\\B")) : -1; + int max_port_a_size = cell->hasPort("\\A") ? GetSize(cell->getPort("\\A")) : -1; + int max_port_b_size = cell->hasPort("\\B") ? GetSize(cell->getPort("\\B")) : -1; if (cell->type.in("$not", "$pos", "$neg", "$and", "$or", "$xor", "$add", "$sub")) { - max_port_a_size = std::min(max_port_a_size, SIZE(cell->getPort("\\Y"))); - max_port_b_size = std::min(max_port_b_size, SIZE(cell->getPort("\\Y"))); + max_port_a_size = std::min(max_port_a_size, GetSize(cell->getPort("\\Y"))); + max_port_b_size = std::min(max_port_b_size, GetSize(cell->getPort("\\Y"))); } bool port_a_signed = false; @@ -201,14 +201,14 @@ struct WreduceWorker if (port_a_signed && cell->type == "$shr") { // do not reduce size of output on $shr cells with signed A inputs } else { - while (SIZE(sig) > 0) + while (GetSize(sig) > 0) { - auto info = mi.query(sig[SIZE(sig)-1]); + auto info = mi.query(sig[GetSize(sig)-1]); - if (info->is_output || SIZE(info->ports) > 1) + if (info->is_output || GetSize(info->ports) > 1) break; - sig.remove(SIZE(sig)-1); + sig.remove(GetSize(sig)-1); bits_removed++; } } @@ -218,8 +218,8 @@ struct WreduceWorker bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); int a_size = 0, b_size = 0; - if (cell->hasPort("\\A")) a_size = SIZE(cell->getPort("\\A")); - if (cell->hasPort("\\B")) b_size = SIZE(cell->getPort("\\B")); + if (cell->hasPort("\\A")) a_size = GetSize(cell->getPort("\\A")); + if (cell->hasPort("\\B")) b_size = GetSize(cell->getPort("\\B")); int max_y_size = std::max(a_size, b_size); @@ -229,14 +229,14 @@ struct WreduceWorker if (cell->type == "$mul") max_y_size = a_size + b_size; - while (SIZE(sig) > 1 && SIZE(sig) > max_y_size) { - module->connect(sig[SIZE(sig)-1], is_signed ? sig[SIZE(sig)-2] : S0); - sig.remove(SIZE(sig)-1); + while (GetSize(sig) > 1 && GetSize(sig) > max_y_size) { + module->connect(sig[GetSize(sig)-1], is_signed ? sig[GetSize(sig)-2] : S0); + sig.remove(GetSize(sig)-1); bits_removed++; } } - if (SIZE(sig) == 0) { + if (GetSize(sig) == 0) { log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); module->remove(cell); return; @@ -244,7 +244,7 @@ struct WreduceWorker if (bits_removed) { log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n", - bits_removed, SIZE(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type)); + bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type)); cell->setPort("\\Y", sig); did_something = true; } @@ -288,19 +288,19 @@ struct WreduceWorker if (w->port_id > 0 || count_nontrivial_wire_attrs(w) > 0) continue; - for (int i = SIZE(w)-1; i >= 0; i--) { + for (int i = GetSize(w)-1; i >= 0; i--) { SigBit bit(w, i); auto info = mi.query(bit); - if (info && (info->is_input || info->is_output || SIZE(info->ports) > 0)) + if (info && (info->is_input || info->is_output || GetSize(info->ports) > 0)) break; unused_top_bits++; } - if (0 < unused_top_bits && unused_top_bits < SIZE(w)) { - log("Removed top %d bits (of %d) from wire %s.%s.\n", unused_top_bits, SIZE(w), log_id(module), log_id(w)); + if (0 < unused_top_bits && unused_top_bits < GetSize(w)) { + log("Removed top %d bits (of %d) from wire %s.%s.\n", unused_top_bits, GetSize(w), log_id(module), log_id(w)); Wire *nw = module->addWire(NEW_ID, w); - nw->width = SIZE(w) - unused_top_bits; - module->connect(nw, SigSpec(w).extract(0, SIZE(nw))); + nw->width = GetSize(w) - unused_top_bits; + module->connect(nw, SigSpec(w).extract(0, GetSize(nw))); module->swap_names(w, nw); } } diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index d7cb38bcd..cd84cfd5b 100644 --- a/passes/proc/proc_arst.cc +++ b/passes/proc/proc_arst.cc @@ -174,7 +174,7 @@ restart_proc_arst: for (auto &action : sync->actions) { RTLIL::SigSpec rspec = action.second; RTLIL::SigSpec rval = RTLIL::SigSpec(RTLIL::State::Sm, rspec.size()); - for (int i = 0; i < SIZE(rspec); i++) + for (int i = 0; i < GetSize(rspec); i++) if (rspec[i].wire == NULL) rval[i] = rspec[i]; RTLIL::SigSpec last_rval; diff --git a/passes/proc/proc_rmdead.cc b/passes/proc/proc_rmdead.cc index d701f00a5..427e0d567 100644 --- a/passes/proc/proc_rmdead.cc +++ b/passes/proc/proc_rmdead.cc @@ -34,7 +34,7 @@ void proc_rmdead(RTLIL::SwitchRule *sw, int &counter) for (size_t i = 0; i < sw->cases.size(); i++) { - bool is_default = SIZE(sw->cases[i]->compare) == 0 && (!pool.empty() || SIZE(sw->signal) == 0); + bool is_default = GetSize(sw->cases[i]->compare) == 0 && (!pool.empty() || GetSize(sw->signal) == 0); for (size_t j = 0; j < sw->cases[i]->compare.size(); j++) { RTLIL::SigSpec sig = sw->cases[i]->compare[j]; diff --git a/passes/sat/eval.cc b/passes/sat/eval.cc index e58a194ec..875896fcd 100644 --- a/passes/sat/eval.cc +++ b/passes/sat/eval.cc @@ -69,7 +69,7 @@ struct BruteForceEquivChecker log_signal(undef2), log_signal(mod1_inputs), log_signal(inputs)); if (ignore_x_mod1) { - for (int i = 0; i < SIZE(sig1); i++) + for (int i = 0; i < GetSize(sig1); i++) if (sig1[i] == RTLIL::State::Sx) sig2[i] = RTLIL::State::Sx; } @@ -290,7 +290,7 @@ struct VlogHammerReporter } else if (rtl_sig.size() > 0) { if (rtl_sig.size() != sig.size()) log_error("Output (y) has a different width in module %s compared to rtl!\n", RTLIL::id2cstr(module->name)); - for (int i = 0; i < SIZE(sig); i++) + for (int i = 0; i < GetSize(sig); i++) if (rtl_sig[i] == RTLIL::State::Sx) sig[i] = RTLIL::State::Sx; } diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index f0c88e52b..d5d1d9160 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -407,7 +407,7 @@ struct SatHelper if (prove_asserts) { RTLIL::SigSpec asserts_a, asserts_en; satgen.getAsserts(asserts_a, asserts_en, timestep); - for (int i = 0; i < SIZE(asserts_a); i++) + for (int i = 0; i < GetSize(asserts_a); i++) log("Import proof for assert: %s when %s.\n", log_signal(asserts_a[i]), log_signal(asserts_en[i])); prove_bits.push_back(satgen.importAsserts(timestep)); } diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc index f8a08841a..03174ea04 100644 --- a/passes/techmap/alumacc.cc +++ b/passes/techmap/alumacc.cc @@ -48,51 +48,51 @@ struct AlumaccWorker RTLIL::SigSpec cached_cf, cached_of, cached_sf; RTLIL::SigSpec get_lt() { - if (SIZE(cached_lt) == 0) + if (GetSize(cached_lt) == 0) cached_lt = is_signed ? alu_cell->module->Xor(NEW_ID, get_of(), get_sf()) : get_cf(); return cached_lt; } RTLIL::SigSpec get_gt() { - if (SIZE(cached_gt) == 0) + if (GetSize(cached_gt) == 0) cached_gt = alu_cell->module->Not(NEW_ID, alu_cell->module->Or(NEW_ID, get_lt(), get_eq())); return cached_gt; } RTLIL::SigSpec get_eq() { - if (SIZE(cached_eq) == 0) + if (GetSize(cached_eq) == 0) cached_eq = alu_cell->module->ReduceAnd(NEW_ID, alu_cell->getPort("\\X")); return cached_eq; } RTLIL::SigSpec get_ne() { - if (SIZE(cached_ne) == 0) + if (GetSize(cached_ne) == 0) cached_ne = alu_cell->module->Not(NEW_ID, get_eq()); return cached_ne; } RTLIL::SigSpec get_cf() { - if (SIZE(cached_cf) == 0) { + if (GetSize(cached_cf) == 0) { cached_cf = alu_cell->getPort("\\CO"); - log_assert(SIZE(cached_cf) >= 1); - cached_cf = alu_cell->module->Not(NEW_ID, cached_cf[SIZE(cached_cf)-1]); + log_assert(GetSize(cached_cf) >= 1); + cached_cf = alu_cell->module->Not(NEW_ID, cached_cf[GetSize(cached_cf)-1]); } return cached_cf; } RTLIL::SigSpec get_of() { - if (SIZE(cached_of) == 0) { + if (GetSize(cached_of) == 0) { cached_of = {alu_cell->getPort("\\CO"), alu_cell->getPort("\\CI")}; - log_assert(SIZE(cached_of) >= 2); - cached_of = alu_cell->module->Xor(NEW_ID, cached_of[SIZE(cached_of)-1], cached_of[SIZE(cached_of)-2]); + log_assert(GetSize(cached_of) >= 2); + cached_of = alu_cell->module->Xor(NEW_ID, cached_of[GetSize(cached_of)-1], cached_of[GetSize(cached_of)-2]); } return cached_of; } RTLIL::SigSpec get_sf() { - if (SIZE(cached_sf) == 0) { + if (GetSize(cached_sf) == 0) { cached_sf = alu_cell->getPort("\\Y"); - cached_sf = cached_sf[SIZE(cached_sf)-1]; + cached_sf = cached_sf[GetSize(cached_sf)-1]; } return cached_sf; } @@ -184,10 +184,10 @@ struct AlumaccWorker return true; if (!port.is_signed && port.do_subtract) return true; - if (SIZE(port.in_b)) - port_sizes.push_back(SIZE(port.in_a) + SIZE(port.in_b)); + if (GetSize(port.in_b)) + port_sizes.push_back(GetSize(port.in_a) + GetSize(port.in_b)); else - port_sizes.push_back(SIZE(port.in_a)); + port_sizes.push_back(GetSize(port.in_a)); } std::sort(port_sizes.begin(), port_sizes.end()); @@ -224,11 +224,11 @@ struct AlumaccWorker if (delete_nodes.count(n)) continue; - for (int i = 0; i < SIZE(n->macc.ports); i++) + for (int i = 0; i < GetSize(n->macc.ports); i++) { auto &port = n->macc.ports[i]; - if (SIZE(port.in_b) > 0 || sig_macc.count(port.in_a) == 0) + if (GetSize(port.in_b) > 0 || sig_macc.count(port.in_a) == 0) continue; auto other_n = sig_macc.at(port.in_a); @@ -236,13 +236,13 @@ struct AlumaccWorker if (other_n->users > 1) continue; - if (SIZE(other_n->y) != SIZE(n->y) && macc_may_overflow(other_n->macc, SIZE(other_n->y), port.is_signed)) + if (GetSize(other_n->y) != GetSize(n->y) && macc_may_overflow(other_n->macc, GetSize(other_n->y), port.is_signed)) continue; log(" merging $macc model for %s into %s.\n", log_id(other_n->cell), log_id(n->cell)); bool do_subtract = port.do_subtract; - for (int j = 0; j < SIZE(other_n->macc.ports); j++) { + for (int j = 0; j < GetSize(other_n->macc.ports); j++) { if (do_subtract) other_n->macc.ports[j].do_subtract = !other_n->macc.ports[j].do_subtract; if (j == 0) @@ -278,38 +278,38 @@ struct AlumaccWorker alunode_t *alunode; for (auto &port : n->macc.ports) - if (SIZE(port.in_b) > 0) { + if (GetSize(port.in_b) > 0) { goto next_macc; - } else if (SIZE(port.in_a) == 1 && !port.is_signed && !port.do_subtract) { + } else if (GetSize(port.in_a) == 1 && !port.is_signed && !port.do_subtract) { C.append(port.in_a); - } else if (SIZE(A) || port.do_subtract) { - if (SIZE(B)) + } else if (GetSize(A) || port.do_subtract) { + if (GetSize(B)) goto next_macc; B = port.in_a; b_signed = port.is_signed; subtract_b = port.do_subtract; } else { - if (SIZE(A)) + if (GetSize(A)) goto next_macc; A = port.in_a; a_signed = port.is_signed; } if (!a_signed || !b_signed) { - if (SIZE(A) == SIZE(n->y)) + if (GetSize(A) == GetSize(n->y)) a_signed = false; - if (SIZE(B) == SIZE(n->y)) + if (GetSize(B) == GetSize(n->y)) b_signed = false; if (a_signed != b_signed) goto next_macc; } - if (SIZE(A) == 0 && SIZE(C) > 0) { + if (GetSize(A) == 0 && GetSize(C) > 0) { A = C[0]; C.remove(0); } - if (SIZE(B) == 0 && SIZE(C) > 0) { + if (GetSize(B) == 0 && GetSize(C) > 0) { B = C[0]; C.remove(0); } @@ -317,10 +317,10 @@ struct AlumaccWorker if (subtract_b) C.append(RTLIL::S1); - if (SIZE(C) > 1) + if (GetSize(C) > 1) goto next_macc; - if (!subtract_b && B < A && SIZE(B)) + if (!subtract_b && B < A && GetSize(B)) std::swap(A, B); log(" creating $alu model for $macc %s.\n", log_id(n->cell)); @@ -356,7 +356,7 @@ struct AlumaccWorker log(" creating $macc cell for %s: %s\n", log_id(n->cell), log_id(cell)); - n->macc.optimize(SIZE(n->y)); + n->macc.optimize(GetSize(n->y)); n->macc.to_cell(cell); cell->setPort("\\Y", n->y); cell->fixup_parameters(); @@ -391,7 +391,7 @@ struct AlumaccWorker RTLIL::SigSpec B = sigmap(cell->getPort("\\B")); RTLIL::SigSpec Y = sigmap(cell->getPort("\\Y")); - if (B < A && SIZE(B)) { + if (B < A && GetSize(B)) { cmp_less = !cmp_less; std::swap(A, B); } @@ -409,7 +409,7 @@ struct AlumaccWorker n->a = A; n->b = B; n->c = RTLIL::S1; - n->y = module->addWire(NEW_ID, std::max(SIZE(A), SIZE(B))); + n->y = module->addWire(NEW_ID, std::max(GetSize(A), GetSize(B))); n->is_signed = is_signed; n->invert_b = true; sig_alu[RTLIL::SigSig(A, B)].insert(n); @@ -431,7 +431,7 @@ struct AlumaccWorker RTLIL::SigSpec B = sigmap(cell->getPort("\\B")); RTLIL::SigSpec Y = sigmap(cell->getPort("\\Y")); - if (B < A && SIZE(B)) + if (B < A && GetSize(B)) std::swap(A, B); alunode_t *n = nullptr; @@ -455,12 +455,12 @@ struct AlumaccWorker for (auto &it1 : sig_alu) for (auto n : it1.second) { - if (SIZE(n->b) == 0 && SIZE(n->c) == 0 && SIZE(n->cmp) == 0) + if (GetSize(n->b) == 0 && GetSize(n->c) == 0 && GetSize(n->cmp) == 0) { n->alu_cell = module->addPos(NEW_ID, n->a, n->y, n->is_signed); log(" creating $pos cell for "); - for (int i = 0; i < SIZE(n->cells); i++) + for (int i = 0; i < GetSize(n->cells); i++) log("%s%s", i ? ", ": "", log_id(n->cells[i])); log(": %s\n", log_id(n->alu_cell)); @@ -471,17 +471,17 @@ struct AlumaccWorker alu_counter++; log(" creating $alu cell for "); - for (int i = 0; i < SIZE(n->cells); i++) + for (int i = 0; i < GetSize(n->cells); i++) log("%s%s", i ? ", ": "", log_id(n->cells[i])); log(": %s\n", log_id(n->alu_cell)); n->alu_cell->setPort("\\A", n->a); n->alu_cell->setPort("\\B", n->b); - n->alu_cell->setPort("\\CI", SIZE(n->c) ? n->c : RTLIL::S0); + n->alu_cell->setPort("\\CI", GetSize(n->c) ? n->c : RTLIL::S0); n->alu_cell->setPort("\\BI", n->invert_b ? RTLIL::S1 : RTLIL::S0); n->alu_cell->setPort("\\Y", n->y); - n->alu_cell->setPort("\\X", module->addWire(NEW_ID, SIZE(n->y))); - n->alu_cell->setPort("\\CO", module->addWire(NEW_ID, SIZE(n->y))); + n->alu_cell->setPort("\\X", module->addWire(NEW_ID, GetSize(n->y))); + n->alu_cell->setPort("\\CO", module->addWire(NEW_ID, GetSize(n->y))); n->alu_cell->fixup_parameters(n->is_signed, n->is_signed); for (auto &it : n->cmp) @@ -498,10 +498,10 @@ struct AlumaccWorker if (cmp_eq) sig.append(n->get_eq()); if (cmp_ne) sig.append(n->get_ne()); - if (SIZE(sig) > 1) + if (GetSize(sig) > 1) sig = module->ReduceOr(NEW_ID, sig); - sig.extend(SIZE(cmp_y)); + sig.extend(GetSize(cmp_y)); module->connect(cmp_y, sig); } diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index 2a6813351..510dcd60b 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -412,7 +412,7 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module) } else if (port.second == 'q') { RTLIL::SigSpec old_sig = cell_connections[std::string("\\") + char(port.second - ('a' - 'A'))]; - sig = module->addWire(NEW_ID, SIZE(old_sig)); + sig = module->addWire(NEW_ID, GetSize(old_sig)); module->addNotGate(NEW_ID, sig, old_sig); } else if ('a' <= port.second && port.second <= 'z') { diff --git a/passes/techmap/maccmap.cc b/passes/techmap/maccmap.cc index 1da97072a..c487cc36a 100644 --- a/passes/techmap/maccmap.cc +++ b/passes/techmap/maccmap.cc @@ -62,16 +62,16 @@ struct MaccmapWorker void add(RTLIL::SigSpec a, RTLIL::SigSpec b, bool is_signed, bool do_subtract) { - if (SIZE(a) < SIZE(b)) + if (GetSize(a) < GetSize(b)) std::swap(a, b); a.extend(width, is_signed); - if (SIZE(b) > width) + if (GetSize(b) > width) b.extend(width, is_signed); - for (int i = 0; i < SIZE(b); i++) - if (is_signed && i+1 == SIZE(b)) + for (int i = 0; i < GetSize(b); i++) + if (is_signed && i+1 == GetSize(b)) { a = {module->Not(NEW_ID, a.extract(i, width-i)), RTLIL::SigSpec(0, i)}; add(module->And(NEW_ID, a, RTLIL::SigSpec(b[i], width)), false, do_subtract); @@ -86,7 +86,7 @@ struct MaccmapWorker void fulladd(RTLIL::SigSpec &in1, RTLIL::SigSpec &in2, RTLIL::SigSpec &in3, RTLIL::SigSpec &out1, RTLIL::SigSpec &out2) { - int start_index = 0, stop_index = SIZE(in1); + int start_index = 0, stop_index = GetSize(in1); while (start_index < stop_index && in1[start_index] == RTLIL::S0 && in2[start_index] == RTLIL::S0 && in3[start_index] == RTLIL::S0) start_index++; @@ -96,18 +96,18 @@ struct MaccmapWorker if (start_index == stop_index) { - out1 = RTLIL::SigSpec(0, SIZE(in1)); - out2 = RTLIL::SigSpec(0, SIZE(in1)); + out1 = RTLIL::SigSpec(0, GetSize(in1)); + out2 = RTLIL::SigSpec(0, GetSize(in1)); } else { - RTLIL::SigSpec out_zeros_lsb(0, start_index), out_zeros_msb(0, SIZE(in1)-stop_index); + RTLIL::SigSpec out_zeros_lsb(0, start_index), out_zeros_msb(0, GetSize(in1)-stop_index); in1 = in1.extract(start_index, stop_index-start_index); in2 = in2.extract(start_index, stop_index-start_index); in3 = in3.extract(start_index, stop_index-start_index); - int width = SIZE(in1); + int width = GetSize(in1); RTLIL::Wire *w1 = module->addWire(NEW_ID, width); RTLIL::Wire *w2 = module->addWire(NEW_ID, width); @@ -165,12 +165,12 @@ struct MaccmapWorker while (1) { - int free_bit_slots = tree_bit_slots(SIZE(summands)) - SIZE(tree_sum_bits); + int free_bit_slots = tree_bit_slots(GetSize(summands)) - GetSize(tree_sum_bits); int max_depth = 0, max_position = 0; for (int i = 0; i < width; i++) - if (max_depth <= SIZE(bits.at(i))) { - max_depth = SIZE(bits.at(i)); + if (max_depth <= GetSize(bits.at(i))) { + max_depth = GetSize(bits.at(i)); max_position = i; } @@ -179,14 +179,14 @@ struct MaccmapWorker int required_bits = 0; for (int i = 0; i <= max_position; i++) - if (SIZE(bits.at(i)) == max_depth) + if (GetSize(bits.at(i)) == max_depth) required_bits += 1 << i; if (required_bits > free_bit_slots) break; for (int i = 0; i <= max_position; i++) - if (SIZE(bits.at(i)) == max_depth) { + if (GetSize(bits.at(i)) == max_depth) { auto it = bits.at(i).begin(); RTLIL::SigBit bit = *it; for (int k = 0; k < (1 << i); k++, free_bit_slots--) @@ -200,23 +200,23 @@ struct MaccmapWorker } if (!tree_sum_bits.empty()) - log(" packed %d (%d) bits / %d words into adder tree\n", SIZE(tree_sum_bits), unique_tree_bits, count_tree_words); + log(" packed %d (%d) bits / %d words into adder tree\n", GetSize(tree_sum_bits), unique_tree_bits, count_tree_words); - if (SIZE(summands) == 0) { + if (GetSize(summands) == 0) { log_assert(tree_sum_bits.empty()); return RTLIL::SigSpec(0, width); } - if (SIZE(summands) == 1) { + if (GetSize(summands) == 1) { log_assert(tree_sum_bits.empty()); return summands.front(); } - while (SIZE(summands) > 2) + while (GetSize(summands) > 2) { std::vector new_summands; - for (int i = 0; i < SIZE(summands); i += 3) - if (i+2 < SIZE(summands)) { + for (int i = 0; i < GetSize(summands); i += 3) + if (i+2 < GetSize(summands)) { RTLIL::SigSpec in1 = summands[i]; RTLIL::SigSpec in2 = summands[i+1]; RTLIL::SigSpec in3 = summands[i+2]; @@ -264,7 +264,7 @@ extern void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap = false void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap) { - int width = SIZE(cell->getPort("\\Y")); + int width = GetSize(cell->getPort("\\Y")); Macc macc; macc.from_cell(cell); @@ -279,15 +279,15 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap) } for (auto &port : macc.ports) - if (SIZE(port.in_b) == 0) + if (GetSize(port.in_b) == 0) log(" %s %s (%d bits, %s)\n", port.do_subtract ? "sub" : "add", log_signal(port.in_a), - SIZE(port.in_a), port.is_signed ? "signed" : "unsigned"); + GetSize(port.in_a), port.is_signed ? "signed" : "unsigned"); else log(" %s %s * %s (%dx%d bits, %s)\n", port.do_subtract ? "sub" : "add", log_signal(port.in_a), log_signal(port.in_b), - SIZE(port.in_a), SIZE(port.in_b), port.is_signed ? "signed" : "unsigned"); + GetSize(port.in_a), GetSize(port.in_b), port.is_signed ? "signed" : "unsigned"); - if (SIZE(macc.bit_ports) != 0) - log(" add bits %s (%d bits)\n", log_signal(macc.bit_ports), SIZE(macc.bit_ports)); + if (GetSize(macc.bit_ports) != 0) + log(" add bits %s (%d bits)\n", log_signal(macc.bit_ports), GetSize(macc.bit_ports)); if (unmap) { @@ -296,10 +296,10 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap) for (auto &port : macc.ports) { summand_t this_summand; - if (SIZE(port.in_b)) { + if (GetSize(port.in_b)) { this_summand.first = module->addWire(NEW_ID, width); module->addMul(NEW_ID, port.in_a, port.in_b, this_summand.first, port.is_signed); - } else if (SIZE(port.in_a) != width) { + } else if (GetSize(port.in_a) != width) { this_summand.first = module->addWire(NEW_ID, width); module->addPos(NEW_ID, port.in_a, this_summand.first, port.is_signed); } else { @@ -312,14 +312,14 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap) for (auto &bit : macc.bit_ports) summands.push_back(summand_t(bit, false)); - if (SIZE(summands) == 0) + if (GetSize(summands) == 0) summands.push_back(summand_t(RTLIL::SigSpec(0, width), false)); - while (SIZE(summands) > 1) + while (GetSize(summands) > 1) { std::vector new_summands; - for (int i = 0; i < SIZE(summands); i += 2) { - if (i+1 < SIZE(summands)) { + for (int i = 0; i < GetSize(summands); i += 2) { + if (i+1 < GetSize(summands)) { summand_t this_summand; this_summand.first = module->addWire(NEW_ID, width); this_summand.second = summands[i].second && summands[i+1].second; @@ -348,7 +348,7 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap) MaccmapWorker worker(module, width); for (auto &port : macc.ports) - if (SIZE(port.in_b) == 0) + if (GetSize(port.in_b) == 0) worker.add(port.in_a, port.is_signed, port.do_subtract); else worker.add(port.in_a, port.in_b, port.is_signed, port.do_subtract); diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index 1cba34336..c3ca29e50 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -32,9 +32,9 @@ static void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell) RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_y = cell->getPort("\\Y"); - sig_a.extend(SIZE(sig_y), cell->parameters.at("\\A_SIGNED").as_bool()); + sig_a.extend(GetSize(sig_y), cell->parameters.at("\\A_SIGNED").as_bool()); - for (int i = 0; i < SIZE(sig_y); i++) { + for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_"); gate->setPort("\\A", sig_a[i]); gate->setPort("\\Y", sig_y[i]); @@ -46,7 +46,7 @@ static void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell) RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_y = cell->getPort("\\Y"); - sig_a.extend_u0(SIZE(sig_y), cell->parameters.at("\\A_SIGNED").as_bool()); + sig_a.extend_u0(GetSize(sig_y), cell->parameters.at("\\A_SIGNED").as_bool()); module->connect(RTLIL::SigSig(sig_y, sig_a)); } @@ -57,14 +57,14 @@ static void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell) RTLIL::SigSpec sig_b = cell->getPort("\\B"); RTLIL::SigSpec sig_y = cell->getPort("\\Y"); - sig_a.extend_u0(SIZE(sig_y), cell->parameters.at("\\A_SIGNED").as_bool()); - sig_b.extend_u0(SIZE(sig_y), cell->parameters.at("\\B_SIGNED").as_bool()); + sig_a.extend_u0(GetSize(sig_y), cell->parameters.at("\\A_SIGNED").as_bool()); + sig_b.extend_u0(GetSize(sig_y), cell->parameters.at("\\B_SIGNED").as_bool()); if (cell->type == "$xnor") { - RTLIL::SigSpec sig_t = module->addWire(NEW_ID, SIZE(sig_y)); + RTLIL::SigSpec sig_t = module->addWire(NEW_ID, GetSize(sig_y)); - for (int i = 0; i < SIZE(sig_y); i++) { + for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_"); gate->setPort("\\A", sig_t[i]); gate->setPort("\\Y", sig_y[i]); @@ -80,7 +80,7 @@ static void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell) if (cell->type == "$xnor") gate_type = "$_XOR_"; log_assert(!gate_type.empty()); - for (int i = 0; i < SIZE(sig_y); i++) { + for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); gate->setPort("\\A", sig_a[i]); gate->setPort("\\B", sig_b[i]); @@ -238,7 +238,7 @@ static void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell) RTLIL::SigSpec sig_b = cell->getPort("\\B"); RTLIL::SigSpec sig_y = cell->getPort("\\Y"); - for (int i = 0; i < SIZE(sig_y); i++) { + for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, "$_MUX_"); gate->setPort("\\A", sig_a[i]); gate->setPort("\\B", sig_b[i]); diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index dc45dacda..0ee45ba39 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -97,7 +97,7 @@ struct TechmapWorker std::map> connbits_map; for (auto conn : cell->connections()) - for (int i = 0; i < SIZE(conn.second); i++) { + for (int i = 0; i < GetSize(conn.second); i++) { RTLIL::SigBit bit = sigmap(conn.second[i]); if (bit.wire == nullptr) { if (verbose) @@ -162,7 +162,7 @@ struct TechmapWorker log(" %s",RTLIL::id2cstr(it.first)); if (autoproc_mode) { Pass::call_on_module(tpl->design, tpl, "proc"); - log_assert(SIZE(tpl->processes) == 0); + log_assert(GetSize(tpl->processes) == 0); } else log_error("Technology map yielded processes -> this is not supported (use -autoproc to run 'proc' automatically).\n"); } @@ -303,7 +303,7 @@ struct TechmapWorker RTLIL::SigSpec sig = sigmap(conn.second); sig.remove_const(); - if (SIZE(sig) == 0) + if (GetSize(sig) == 0) continue; for (auto &tpl_name : celltypeMap.at(cell_type)) { @@ -383,7 +383,7 @@ struct TechmapWorker int port_counter = 1; for (auto &c : extmapper_cell->connections_) { - RTLIL::Wire *w = extmapper_module->addWire(c.first, SIZE(c.second)); + RTLIL::Wire *w = extmapper_module->addWire(c.first, GetSize(c.second)); if (w->name == "\\Y" || w->name == "\\Q") w->port_output = true; else @@ -630,7 +630,7 @@ struct TechmapWorker } for (auto conn : cell->connections()) - for (int i = 0; i < SIZE(conn.second); i++) + for (int i = 0; i < GetSize(conn.second); i++) { RTLIL::SigBit bit = sigmap(conn.second[i]); RTLIL::SigBit tplbit(tpl->wire(conn.first), i); diff --git a/passes/tests/test_abcloop.cc b/passes/tests/test_abcloop.cc index 1ede137ee..853339b95 100644 --- a/passes/tests/test_abcloop.cc +++ b/passes/tests/test_abcloop.cc @@ -36,7 +36,7 @@ static uint32_t xorshift32(uint32_t limit) { static RTLIL::Wire *getw(std::vector &wires, RTLIL::Wire *w) { while (1) { - int idx = xorshift32(SIZE(wires)); + int idx = xorshift32(GetSize(wires)); if (wires[idx] != w && !wires[idx]->port_output) return wires[idx]; } @@ -144,7 +144,7 @@ static void test_abcloop() for (int i = 0; i < 16; i++) { std::vector assumptions; - for (int j = 0; j < SIZE(in_vec); j++) + for (int j = 0; j < GetSize(in_vec); j++) assumptions.push_back((i & (1 << j)) ? in_vec.at(j) : inverse_in_vec.at(j)); std::vector results; @@ -197,7 +197,7 @@ static void test_abcloop() for (int i = 0; i < 16; i++) { std::vector assumptions; - for (int j = 0; j < SIZE(in_vec); j++) + for (int j = 0; j < GetSize(in_vec); j++) assumptions.push_back((i & (1 << j)) ? in_vec.at(j) : inverse_in_vec.at(j)); for (int j = 0; j < 4; j++) @@ -265,13 +265,13 @@ struct TestAbcloopPass : public Pass { xorshift32_state = 0; int argidx; - for (argidx = 1; argidx < SIZE(args); argidx++) + for (argidx = 1; argidx < GetSize(args); argidx++) { - if (args[argidx] == "-n" && argidx+1 < SIZE(args)) { + if (args[argidx] == "-n" && argidx+1 < GetSize(args)) { num_iter = atoi(args[++argidx].c_str()); continue; } - if (args[argidx] == "-s" && argidx+1 < SIZE(args)) { + if (args[argidx] == "-s" && argidx+1 < GetSize(args)) { xorshift32_state = atoi(args[++argidx].c_str()); continue; } diff --git a/passes/tests/test_autotb.cc b/passes/tests/test_autotb.cc index 05caf6b21..9713ea061 100644 --- a/passes/tests/test_autotb.cc +++ b/passes/tests/test_autotb.cc @@ -336,9 +336,9 @@ struct TestAutotbBackend : public Backend { log_header("Executing TEST_AUTOTB backend (auto-generate pseudo-random test benches).\n"); int argidx; - for (argidx = 1; argidx < SIZE(args); argidx++) + for (argidx = 1; argidx < GetSize(args); argidx++) { - if (args[argidx] == "-n" && argidx+1 < SIZE(args)) { + if (args[argidx] == "-n" && argidx+1 < GetSize(args)) { num_iter = atoi(args[++argidx].c_str()); continue; } diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index d611d56c3..03fb31d28 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -213,12 +213,12 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, cell->setPort("\\BI", wire); wire = module->addWire("\\X"); - wire->width = SIZE(cell->getPort("\\Y")); + wire->width = GetSize(cell->getPort("\\Y")); wire->port_output = true; cell->setPort("\\X", wire); wire = module->addWire("\\CO"); - wire->width = SIZE(cell->getPort("\\Y")); + wire->width = GetSize(cell->getPort("\\Y")); wire->port_output = true; cell->setPort("\\CO", wire); } @@ -230,25 +230,25 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, { RTLIL::SigSpec sig = conn.second; - if (SIZE(sig) == 0 || sig[0].wire == nullptr || sig[0].wire->port_output) + if (GetSize(sig) == 0 || sig[0].wire == nullptr || sig[0].wire->port_output) continue; int n, m; switch (xorshift32(5)) { case 0: - n = xorshift32(SIZE(sig) + 1); + n = xorshift32(GetSize(sig) + 1); for (int i = 0; i < n; i++) sig[i] = xorshift32(2) == 1 ? RTLIL::S1 : RTLIL::S0; break; case 1: - n = xorshift32(SIZE(sig) + 1); - for (int i = n; i < SIZE(sig); i++) + n = xorshift32(GetSize(sig) + 1); + for (int i = n; i < GetSize(sig); i++) sig[i] = xorshift32(2) == 1 ? RTLIL::S1 : RTLIL::S0; break; case 2: - n = xorshift32(SIZE(sig)); - m = xorshift32(SIZE(sig)); + n = xorshift32(GetSize(sig)); + m = xorshift32(GetSize(sig)); for (int i = std::min(n, m); i < std::max(n, m); i++) sig[i] = xorshift32(2) == 1 ? RTLIL::S1 : RTLIL::S0; break; @@ -290,19 +290,19 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: for (auto port : gold_mod->ports) { RTLIL::Wire *wire = gold_mod->wire(port); if (wire->port_input) - vlog_file << stringf(" reg [%d:0] %s;\n", SIZE(wire)-1, log_id(wire)); + vlog_file << stringf(" reg [%d:0] %s;\n", GetSize(wire)-1, log_id(wire)); else - vlog_file << stringf(" wire [%d:0] %s_expr, %s_noexpr;\n", SIZE(wire)-1, log_id(wire), log_id(wire)); + vlog_file << stringf(" wire [%d:0] %s_expr, %s_noexpr;\n", GetSize(wire)-1, log_id(wire), log_id(wire)); } vlog_file << stringf(" %s_expr uut_expr(", uut_name.c_str()); - for (int i = 0; i < SIZE(gold_mod->ports); i++) + for (int i = 0; i < GetSize(gold_mod->ports); i++) vlog_file << stringf("%s.%s(%s%s)", i ? ", " : "", log_id(gold_mod->ports[i]), log_id(gold_mod->ports[i]), gold_mod->wire(gold_mod->ports[i])->port_input ? "" : "_expr"); vlog_file << stringf(");\n"); vlog_file << stringf(" %s_expr uut_noexpr(", uut_name.c_str()); - for (int i = 0; i < SIZE(gold_mod->ports); i++) + for (int i = 0; i < GetSize(gold_mod->ports); i++) vlog_file << stringf("%s.%s(%s%s)", i ? ", " : "", log_id(gold_mod->ports[i]), log_id(gold_mod->ports[i]), gold_mod->wire(gold_mod->ports[i])->port_input ? "" : "_noexpr"); vlog_file << stringf(");\n"); @@ -330,18 +330,18 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: log_assert(gold_wire != nullptr); log_assert(gate_wire != nullptr); log_assert(gold_wire->port_input == gate_wire->port_input); - log_assert(SIZE(gold_wire) == SIZE(gate_wire)); + log_assert(GetSize(gold_wire) == GetSize(gate_wire)); if (!gold_wire->port_input) continue; RTLIL::Const in_value; - for (int i = 0; i < SIZE(gold_wire); i++) + for (int i = 0; i < GetSize(gold_wire); i++) in_value.bits.push_back(xorshift32(2) ? RTLIL::S1 : RTLIL::S0); if (xorshift32(4) == 0) { int inv_chance = 1 + xorshift32(8); - for (int i = 0; i < SIZE(gold_wire); i++) + for (int i = 0; i < GetSize(gold_wire); i++) if (xorshift32(inv_chance) == 0) in_value.bits[i] = RTLIL::Sx; } @@ -355,7 +355,7 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: gold_ce.set(gold_wire, in_value); gate_ce.set(gate_wire, in_value); - if (vlog_file.is_open() && SIZE(in_value) > 0) { + if (vlog_file.is_open() && GetSize(in_value) > 0) { vlog_file << stringf(" %s = 'b%s;\n", log_id(gold_wire), in_value.as_string().c_str()); if (!vlog_pattern_info.empty()) vlog_pattern_info += " "; @@ -374,7 +374,7 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: log_assert(gold_wire != nullptr); log_assert(gate_wire != nullptr); log_assert(gold_wire->port_output == gate_wire->port_output); - log_assert(SIZE(gold_wire) == SIZE(gate_wire)); + log_assert(GetSize(gold_wire) == GetSize(gate_wire)); if (!gold_wire->port_output) continue; @@ -389,7 +389,7 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: log_error("Failed to eval %s in gate module.\n", log_id(gate_wire)); bool gold_gate_mismatch = false; - for (int i = 0; i < SIZE(gold_wire); i++) { + for (int i = 0; i < GetSize(gold_wire); i++) { if (gold_outval[i] == RTLIL::Sx) continue; if (gold_outval[i] == gate_outval[i]) @@ -409,9 +409,9 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: if (vlog_file.is_open()) { vlog_file << stringf(" $display(\"[%s] %s expected: %%b, expr: %%b, noexpr: %%b\", %d'b%s, %s_expr, %s_noexpr);\n", - vlog_pattern_info.c_str(), log_id(gold_wire), SIZE(gold_outval), gold_outval.as_string().c_str(), log_id(gold_wire), log_id(gold_wire)); - vlog_file << stringf(" if (%s_expr !== %d'b%s) begin $display(\"ERROR\"); $finish; end\n", log_id(gold_wire), SIZE(gold_outval), gold_outval.as_string().c_str()); - vlog_file << stringf(" if (%s_noexpr !== %d'b%s) begin $display(\"ERROR\"); $finish; end\n", log_id(gold_wire), SIZE(gold_outval), gold_outval.as_string().c_str()); + vlog_pattern_info.c_str(), log_id(gold_wire), GetSize(gold_outval), gold_outval.as_string().c_str(), log_id(gold_wire), log_id(gold_wire)); + vlog_file << stringf(" if (%s_expr !== %d'b%s) begin $display(\"ERROR\"); $finish; end\n", log_id(gold_wire), GetSize(gold_outval), gold_outval.as_string().c_str()); + vlog_file << stringf(" if (%s_noexpr !== %d'b%s) begin $display(\"ERROR\"); $finish; end\n", log_id(gold_wire), GetSize(gold_outval), gold_outval.as_string().c_str()); } } @@ -431,12 +431,12 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: if (verbose) { log("SAT 1: "); - for (int i = SIZE(out_sig)-1; i >= 0; i--) + for (int i = GetSize(out_sig)-1; i >= 0; i--) log("%c", sat1_model_value.at(i) ? '1' : '0'); log("\n"); } - for (int i = 0; i < SIZE(out_sig); i++) { + for (int i = 0; i < GetSize(out_sig); i++) { if (out_val[i] != RTLIL::S0 && out_val[i] != RTLIL::S1) continue; if (out_val[i] == RTLIL::S0 && sat1_model_value.at(i) == false) @@ -466,13 +466,13 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: if (verbose) { log("SAT 2: "); - for (int i = SIZE(out_sig)-1; i >= 0; i--) - log("%c", sat2_model_value.at(SIZE(out_sig) + i) ? 'x' : sat2_model_value.at(i) ? '1' : '0'); + for (int i = GetSize(out_sig)-1; i >= 0; i--) + log("%c", sat2_model_value.at(GetSize(out_sig) + i) ? 'x' : sat2_model_value.at(i) ? '1' : '0'); log("\n"); } - for (int i = 0; i < SIZE(out_sig); i++) { - if (sat2_model_value.at(SIZE(out_sig) + i)) { + for (int i = 0; i < GetSize(out_sig); i++) { + if (sat2_model_value.at(GetSize(out_sig) + i)) { if (out_val[i] != RTLIL::S0 && out_val[i] != RTLIL::S1) continue; } else { @@ -553,26 +553,26 @@ struct TestCellPass : public Pass { bool nosat = false; int argidx; - for (argidx = 1; argidx < SIZE(args); argidx++) + for (argidx = 1; argidx < GetSize(args); argidx++) { - if (args[argidx] == "-n" && argidx+1 < SIZE(args)) { + if (args[argidx] == "-n" && argidx+1 < GetSize(args)) { num_iter = atoi(args[++argidx].c_str()); continue; } - if (args[argidx] == "-s" && argidx+1 < SIZE(args)) { + if (args[argidx] == "-s" && argidx+1 < GetSize(args)) { xorshift32_state = atoi(args[++argidx].c_str()); continue; } - if (args[argidx] == "-map" && argidx+1 < SIZE(args)) { + if (args[argidx] == "-map" && argidx+1 < GetSize(args)) { techmap_cmd += " -map " + args[++argidx]; continue; } - if (args[argidx] == "-f" && argidx+1 < SIZE(args)) { + if (args[argidx] == "-f" && argidx+1 < GetSize(args)) { ilang_file = args[++argidx]; num_iter = 1; continue; } - if (args[argidx] == "-script" && argidx+1 < SIZE(args)) { + if (args[argidx] == "-script" && argidx+1 < GetSize(args)) { techmap_cmd = "script " + args[++argidx]; continue; } @@ -592,7 +592,7 @@ struct TestCellPass : public Pass { verbose = true; continue; } - if (args[argidx] == "-vlog" && argidx+1 < SIZE(args)) { + if (args[argidx] == "-vlog" && argidx+1 < GetSize(args)) { vlog_file.open(args[++argidx], std::ios_base::trunc); if (!vlog_file.is_open()) log_cmd_error("Failed to open output file `%s'.\n", args[argidx].c_str()); @@ -663,7 +663,7 @@ struct TestCellPass : public Pass { cell_types["$macc"] = "*"; cell_types["$fa"] = "*"; - for (; argidx < SIZE(args); argidx++) + for (; argidx < GetSize(args); argidx++) { if (args[argidx].rfind("-", 0) == 0) log_cmd_error("Unexpected option: %s\n", args[argidx].c_str()); @@ -684,7 +684,7 @@ struct TestCellPass : public Pass { charcount = 0; } else cell_type_list += " " + it.first; - charcount += SIZE(it.first); + charcount += GetSize(it.first); } log_cmd_error("The cell type `%s' is currently not supported. Try one of these:%s\n", args[argidx].c_str(), cell_type_list.c_str()); From 7cb0d3aa1acf37025e82846f809d066356a98843 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 10 Oct 2014 17:06:02 +0200 Subject: [PATCH 018/492] Renamed TRUE/FALSE to CONST_TRUE/CONST_FALSE because of name collision on Win32 --- kernel/satgen.h | 104 +++++++++++++++++----------------- libs/ezsat/ezminisat.cc | 4 +- libs/ezsat/ezsat.cc | 120 ++++++++++++++++++++-------------------- libs/ezsat/ezsat.h | 6 +- passes/sat/eval.cc | 2 +- 5 files changed, 118 insertions(+), 118 deletions(-) diff --git a/kernel/satgen.h b/kernel/satgen.h index 2759b3927..779c97506 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -66,7 +66,7 @@ struct SatGen if (model_undef && dup_undef && bit == RTLIL::State::Sx) vec.push_back(ez->frozen_literal()); else - vec.push_back(bit == (undef_mode ? RTLIL::State::Sx : RTLIL::State::S1) ? ez->TRUE : ez->FALSE); + vec.push_back(bit == (undef_mode ? RTLIL::State::Sx : RTLIL::State::S1) ? ez->CONST_TRUE : ez->CONST_FALSE); } else { std::string name = pf + stringf(bit.wire->width == 1 ? "%s" : "%s [%d]", RTLIL::id2cstr(bit.wire->name), bit.offset); vec.push_back(ez->frozen_literal(name)); @@ -160,9 +160,9 @@ struct SatGen if (!forced_signed && cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters.count("\\B_SIGNED") > 0) is_signed = cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool(); while (vec_a.size() < vec_b.size() || vec_a.size() < y_width) - vec_a.push_back(is_signed && vec_a.size() > 0 ? vec_a.back() : ez->FALSE); + vec_a.push_back(is_signed && vec_a.size() > 0 ? vec_a.back() : ez->CONST_FALSE); while (vec_b.size() < vec_a.size() || vec_b.size() < y_width) - vec_b.push_back(is_signed && vec_b.size() > 0 ? vec_b.back() : ez->FALSE); + vec_b.push_back(is_signed && vec_b.size() > 0 ? vec_b.back() : ez->CONST_FALSE); } void extendSignalWidth(std::vector &vec_a, std::vector &vec_b, std::vector &vec_y, RTLIL::Cell *cell, bool forced_signed = false) @@ -176,7 +176,7 @@ struct SatGen { bool is_signed = forced_signed || (cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool()); while (vec_a.size() < vec_y.size()) - vec_a.push_back(is_signed && vec_a.size() > 0 ? vec_a.back() : ez->FALSE); + vec_a.push_back(is_signed && vec_a.size() > 0 ? vec_a.back() : ez->CONST_FALSE); while (vec_y.size() < vec_a.size()) vec_y.push_back(ez->literal()); } @@ -226,7 +226,7 @@ struct SatGen if (is_arith_compare) { for (size_t i = 1; i < undef_y.size(); i++) - ez->SET(ez->FALSE, undef_y.at(i)); + ez->SET(ez->CONST_FALSE, undef_y.at(i)); ez->SET(undef_y_bit, undef_y.at(0)); } else { std::vector undef_y_bits(undef_y.size(), undef_y_bit); @@ -307,7 +307,7 @@ struct SatGen int a = importDefSigSpec(cell->getPort("\\A"), timestep).at(0); int b = importDefSigSpec(cell->getPort("\\B"), timestep).at(0); int c = importDefSigSpec(cell->getPort("\\C"), timestep).at(0); - int d = three_mode ? (aoi_mode ? ez->TRUE : ez->FALSE) : importDefSigSpec(cell->getPort("\\D"), timestep).at(0); + int d = three_mode ? (aoi_mode ? ez->CONST_TRUE : ez->CONST_FALSE) : importDefSigSpec(cell->getPort("\\D"), timestep).at(0); int y = importDefSigSpec(cell->getPort("\\Y"), timestep).at(0); int yy = model_undef ? ez->literal() : y; @@ -321,7 +321,7 @@ struct SatGen int undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep).at(0); int undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep).at(0); int undef_c = importUndefSigSpec(cell->getPort("\\C"), timestep).at(0); - int undef_d = three_mode ? ez->FALSE : importUndefSigSpec(cell->getPort("\\D"), timestep).at(0); + int undef_d = three_mode ? ez->CONST_FALSE : importUndefSigSpec(cell->getPort("\\D"), timestep).at(0); int undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep).at(0); if (aoi_mode) @@ -433,14 +433,14 @@ struct SatGen std::vector undef_s = importUndefSigSpec(cell->getPort("\\S"), timestep); std::vector undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep); - int maybe_one_hot = ez->FALSE; - int maybe_many_hot = ez->FALSE; + int maybe_one_hot = ez->CONST_FALSE; + int maybe_many_hot = ez->CONST_FALSE; - int sure_one_hot = ez->FALSE; - int sure_many_hot = ez->FALSE; + int sure_one_hot = ez->CONST_FALSE; + int sure_many_hot = ez->CONST_FALSE; - std::vector bits_set = std::vector(undef_y.size(), ez->FALSE); - std::vector bits_clr = std::vector(undef_y.size(), ez->FALSE); + std::vector bits_set = std::vector(undef_y.size(), ez->CONST_FALSE); + std::vector bits_clr = std::vector(undef_y.size(), ez->CONST_FALSE); for (size_t i = 0; i < s.size(); i++) { @@ -482,7 +482,7 @@ struct SatGen if (cell->type == "$pos") { ez->assume(ez->vec_eq(a, yy)); } else { - std::vector zero(a.size(), ez->FALSE); + std::vector zero(a.size(), ez->CONST_FALSE); ez->assume(ez->vec_eq(ez->vec_sub(zero, a), yy)); } @@ -524,7 +524,7 @@ struct SatGen if (cell->type == "$logic_not") ez->SET(ez->NOT(ez->expression(ez->OpOr, a)), yy.at(0)); for (size_t i = 1; i < y.size(); i++) - ez->SET(ez->FALSE, yy.at(i)); + ez->SET(ez->CONST_FALSE, yy.at(i)); if (model_undef) { @@ -546,7 +546,7 @@ struct SatGen log_abort(); for (size_t i = 1; i < undef_y.size(); i++) - ez->SET(ez->FALSE, undef_y.at(i)); + ez->SET(ez->CONST_FALSE, undef_y.at(i)); undefGating(y, yy, undef_y); } @@ -569,7 +569,7 @@ struct SatGen else ez->SET(ez->expression(ez->OpOr, a, b), yy.at(0)); for (size_t i = 1; i < y.size(); i++) - ez->SET(ez->FALSE, yy.at(i)); + ez->SET(ez->CONST_FALSE, yy.at(i)); if (model_undef) { @@ -592,7 +592,7 @@ struct SatGen log_abort(); for (size_t i = 1; i < undef_y.size(); i++) - ez->SET(ez->FALSE, undef_y.at(i)); + ez->SET(ez->CONST_FALSE, undef_y.at(i)); undefGating(y, yy, undef_y); } @@ -630,7 +630,7 @@ struct SatGen if (cell->type == "$gt") ez->SET(is_signed ? ez->vec_gt_signed(a, b) : ez->vec_gt_unsigned(a, b), yy.at(0)); for (size_t i = 1; i < y.size(); i++) - ez->SET(ez->FALSE, yy.at(i)); + ez->SET(ez->CONST_FALSE, yy.at(i)); if (model_undef && (cell->type == "$eqx" || cell->type == "$nex")) { @@ -645,7 +645,7 @@ struct SatGen yy.at(0) = ez->OR(yy.at(0), ez->vec_ne(undef_a, undef_b)); for (size_t i = 0; i < y.size(); i++) - ez->SET(ez->FALSE, undef_y.at(i)); + ez->SET(ez->CONST_FALSE, undef_y.at(i)); ez->assume(ez->vec_eq(y, yy)); } @@ -667,7 +667,7 @@ struct SatGen int undef_y_bit = ez->AND(undef_any, ez->NOT(masked_ne)); for (size_t i = 1; i < undef_y.size(); i++) - ez->SET(ez->FALSE, undef_y.at(i)); + ez->SET(ez->CONST_FALSE, undef_y.at(i)); ez->SET(undef_y_bit, undef_y.at(0)); undefGating(y, yy, undef_y); @@ -689,7 +689,7 @@ struct SatGen std::vector b = importDefSigSpec(cell->getPort("\\B"), timestep); std::vector y = importDefSigSpec(cell->getPort("\\Y"), timestep); - int extend_bit = ez->FALSE; + int extend_bit = ez->CONST_FALSE; if (!cell->type.in("$shift", "$shiftx") && cell->parameters["\\A_SIGNED"].as_bool()) extend_bit = a.back(); @@ -703,16 +703,16 @@ struct SatGen std::vector shifted_a; if (cell->type == "$shl" || cell->type == "$sshl") - shifted_a = ez->vec_shift_left(a, b, false, ez->FALSE, ez->FALSE); + shifted_a = ez->vec_shift_left(a, b, false, ez->CONST_FALSE, ez->CONST_FALSE); if (cell->type == "$shr") - shifted_a = ez->vec_shift_right(a, b, false, ez->FALSE, ez->FALSE); + shifted_a = ez->vec_shift_right(a, b, false, ez->CONST_FALSE, ez->CONST_FALSE); if (cell->type == "$sshr") - shifted_a = ez->vec_shift_right(a, b, false, cell->parameters["\\A_SIGNED"].as_bool() ? a.back() : ez->FALSE, ez->FALSE); + shifted_a = ez->vec_shift_right(a, b, false, cell->parameters["\\A_SIGNED"].as_bool() ? a.back() : ez->CONST_FALSE, ez->CONST_FALSE); if (cell->type == "$shift" || cell->type == "$shiftx") - shifted_a = ez->vec_shift_right(a, b, cell->parameters["\\B_SIGNED"].as_bool(), ez->FALSE, ez->FALSE); + shifted_a = ez->vec_shift_right(a, b, cell->parameters["\\B_SIGNED"].as_bool(), ez->CONST_FALSE, ez->CONST_FALSE); ez->assume(ez->vec_eq(shifted_a, yy)); @@ -723,7 +723,7 @@ struct SatGen std::vector undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep); std::vector undef_a_shifted; - extend_bit = cell->type == "$shiftx" ? ez->TRUE : ez->FALSE; + extend_bit = cell->type == "$shiftx" ? ez->CONST_TRUE : ez->CONST_FALSE; if (!cell->type.in("$shift", "$shiftx") && cell->parameters["\\A_SIGNED"].as_bool()) extend_bit = undef_a.back(); @@ -733,19 +733,19 @@ struct SatGen undef_a.push_back(extend_bit); if (cell->type == "$shl" || cell->type == "$sshl") - undef_a_shifted = ez->vec_shift_left(undef_a, b, false, ez->FALSE, ez->FALSE); + undef_a_shifted = ez->vec_shift_left(undef_a, b, false, ez->CONST_FALSE, ez->CONST_FALSE); if (cell->type == "$shr") - undef_a_shifted = ez->vec_shift_right(undef_a, b, false, ez->FALSE, ez->FALSE); + undef_a_shifted = ez->vec_shift_right(undef_a, b, false, ez->CONST_FALSE, ez->CONST_FALSE); if (cell->type == "$sshr") - undef_a_shifted = ez->vec_shift_right(undef_a, b, false, cell->parameters["\\A_SIGNED"].as_bool() ? undef_a.back() : ez->FALSE, ez->FALSE); + undef_a_shifted = ez->vec_shift_right(undef_a, b, false, cell->parameters["\\A_SIGNED"].as_bool() ? undef_a.back() : ez->CONST_FALSE, ez->CONST_FALSE); if (cell->type == "$shift") - undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters["\\B_SIGNED"].as_bool(), ez->FALSE, ez->FALSE); + undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters["\\B_SIGNED"].as_bool(), ez->CONST_FALSE, ez->CONST_FALSE); if (cell->type == "$shiftx") - undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters["\\B_SIGNED"].as_bool(), ez->TRUE, ez->TRUE); + undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters["\\B_SIGNED"].as_bool(), ez->CONST_TRUE, ez->CONST_TRUE); int undef_any_b = ez->expression(ezSAT::OpOr, undef_b); std::vector undef_all_y_bits(undef_y.size(), undef_any_b); @@ -764,10 +764,10 @@ struct SatGen std::vector yy = model_undef ? ez->vec_var(y.size()) : y; - std::vector tmp(a.size(), ez->FALSE); + std::vector tmp(a.size(), ez->CONST_FALSE); for (int i = 0; i < int(a.size()); i++) { - std::vector shifted_a(a.size(), ez->FALSE); + std::vector shifted_a(a.size(), ez->CONST_FALSE); for (int j = i; j < int(a.size()); j++) shifted_a.at(j) = a.at(j-i); tmp = ez->vec_ite(b.at(i), ez->vec_add(tmp, shifted_a), tmp); @@ -791,7 +791,7 @@ struct SatGen Macc macc; macc.from_cell(cell); - std::vector tmp(GetSize(y), ez->FALSE); + std::vector tmp(GetSize(y), ez->CONST_FALSE); for (auto &port : macc.ports) { @@ -799,17 +799,17 @@ struct SatGen std::vector in_b = importDefSigSpec(port.in_b, timestep); while (GetSize(in_a) < GetSize(y)) - in_a.push_back(port.is_signed && !in_a.empty() ? in_a.back() : ez->FALSE); + in_a.push_back(port.is_signed && !in_a.empty() ? in_a.back() : ez->CONST_FALSE); in_a.resize(GetSize(y)); if (GetSize(in_b)) { while (GetSize(in_b) < GetSize(y)) - in_b.push_back(port.is_signed && !in_b.empty() ? in_b.back() : ez->FALSE); + in_b.push_back(port.is_signed && !in_b.empty() ? in_b.back() : ez->CONST_FALSE); in_b.resize(GetSize(y)); for (int i = 0; i < GetSize(in_b); i++) { - std::vector shifted_a(in_a.size(), ez->FALSE); + std::vector shifted_a(in_a.size(), ez->CONST_FALSE); for (int j = i; j < int(in_a.size()); j++) shifted_a.at(j) = in_a.at(j-i); if (port.do_subtract) @@ -828,7 +828,7 @@ struct SatGen } for (int i = 0; i < GetSize(b); i++) { - std::vector val(GetSize(y), ez->FALSE); + std::vector val(GetSize(y), ez->CONST_FALSE); val.at(0) = b.at(i); tmp = ez->vec_add(tmp, val); } @@ -871,14 +871,14 @@ struct SatGen } std::vector chain_buf = a_u; - std::vector y_u(a_u.size(), ez->FALSE); + std::vector y_u(a_u.size(), ez->CONST_FALSE); for (int i = int(a.size())-1; i >= 0; i--) { - chain_buf.insert(chain_buf.end(), chain_buf.size(), ez->FALSE); + chain_buf.insert(chain_buf.end(), chain_buf.size(), ez->CONST_FALSE); - std::vector b_shl(i, ez->FALSE); + std::vector b_shl(i, ez->CONST_FALSE); b_shl.insert(b_shl.end(), b_u.begin(), b_u.end()); - b_shl.insert(b_shl.end(), chain_buf.size()-b_shl.size(), ez->FALSE); + b_shl.insert(b_shl.end(), chain_buf.size()-b_shl.size(), ez->CONST_FALSE); y_u.at(i) = ez->vec_ge_unsigned(chain_buf, b_shl); chain_buf = ez->vec_ite(y_u.at(i), ez->vec_sub(chain_buf, b_shl), chain_buf); @@ -905,13 +905,13 @@ struct SatGen std::vector div_zero_result; if (cell->type == "$div") { if (cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool()) { - std::vector all_ones(y.size(), ez->TRUE); - std::vector only_first_one(y.size(), ez->FALSE); - only_first_one.at(0) = ez->TRUE; + std::vector all_ones(y.size(), ez->CONST_TRUE); + std::vector only_first_one(y.size(), ez->CONST_FALSE); + only_first_one.at(0) = ez->CONST_TRUE; div_zero_result = ez->vec_ite(a.back(), only_first_one, all_ones); } else { - div_zero_result.insert(div_zero_result.end(), cell->getPort("\\A").size(), ez->TRUE); - div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->FALSE); + div_zero_result.insert(div_zero_result.end(), cell->getPort("\\A").size(), ez->CONST_TRUE); + div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->CONST_FALSE); } } else { int copy_a_bits = std::min(cell->getPort("\\A").size(), cell->getPort("\\B").size()); @@ -919,7 +919,7 @@ struct SatGen if (cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool()) div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), div_zero_result.back()); else - div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->FALSE); + div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->CONST_FALSE); } ez->assume(ez->vec_eq(yy, ez->vec_ite(ez->expression(ezSAT::OpOr, b), y_tmp, div_zero_result))); } @@ -939,15 +939,15 @@ struct SatGen std::vector lut; for (auto bit : cell->getParam("\\LUT").bits) - lut.push_back(bit == RTLIL::S1 ? ez->TRUE : ez->FALSE); + lut.push_back(bit == RTLIL::S1 ? ez->CONST_TRUE : ez->CONST_FALSE); while (GetSize(lut) < (1 << GetSize(a))) - lut.push_back(ez->FALSE); + lut.push_back(ez->CONST_FALSE); lut.resize(1 << GetSize(a)); if (model_undef) { std::vector undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep); - std::vector t(lut), u(GetSize(t), ez->FALSE); + std::vector t(lut), u(GetSize(t), ez->CONST_FALSE); for (int i = GetSize(a)-1; i >= 0; i--) { diff --git a/libs/ezsat/ezminisat.cc b/libs/ezsat/ezminisat.cc index dc4e5d283..267355ada 100644 --- a/libs/ezsat/ezminisat.cc +++ b/libs/ezsat/ezminisat.cc @@ -37,8 +37,8 @@ ezMiniSAT::ezMiniSAT() : minisatSolver(NULL) minisatSolver = NULL; foundContradiction = false; - freeze(TRUE); - freeze(FALSE); + freeze(CONST_TRUE); + freeze(CONST_FALSE); } ezMiniSAT::~ezMiniSAT() diff --git a/libs/ezsat/ezsat.cc b/libs/ezsat/ezsat.cc index 13ed112ed..754691f7b 100644 --- a/libs/ezsat/ezsat.cc +++ b/libs/ezsat/ezsat.cc @@ -25,8 +25,8 @@ #include -const int ezSAT::TRUE = 1; -const int ezSAT::FALSE = 2; +const int ezSAT::CONST_TRUE = 1; +const int ezSAT::CONST_FALSE = 2; ezSAT::ezSAT() { @@ -42,11 +42,11 @@ ezSAT::ezSAT() solverTimeout = 0; solverTimoutStatus = false; - literal("TRUE"); - literal("FALSE"); + literal("CONST_TRUE"); + literal("CONST_FALSE"); - assert(literal("TRUE") == TRUE); - assert(literal("FALSE") == FALSE); + assert(literal("CONST_TRUE") == CONST_TRUE); + assert(literal("CONST_FALSE") == CONST_FALSE); } ezSAT::~ezSAT() @@ -55,7 +55,7 @@ ezSAT::~ezSAT() int ezSAT::value(bool val) { - return val ? TRUE : FALSE; + return val ? CONST_TRUE : CONST_FALSE; } int ezSAT::literal() @@ -105,11 +105,11 @@ int ezSAT::expression(OpId op, const std::vector &args) { if (arg == 0) continue; - if (op == OpAnd && arg == TRUE) + if (op == OpAnd && arg == CONST_TRUE) continue; - if ((op == OpOr || op == OpXor) && arg == FALSE) + if ((op == OpOr || op == OpXor) && arg == CONST_FALSE) continue; - if (op == OpXor && arg == TRUE) { + if (op == OpXor && arg == CONST_TRUE) { xorRemovedOddTrues = !xorRemovedOddTrues; continue; } @@ -131,29 +131,29 @@ int ezSAT::expression(OpId op, const std::vector &args) { case OpNot: assert(myArgs.size() == 1); - if (myArgs[0] == TRUE) - return FALSE; - if (myArgs[0] == FALSE) - return TRUE; + if (myArgs[0] == CONST_TRUE) + return CONST_FALSE; + if (myArgs[0] == CONST_FALSE) + return CONST_TRUE; break; case OpAnd: if (myArgs.size() == 0) - return TRUE; + return CONST_TRUE; if (myArgs.size() == 1) return myArgs[0]; break; case OpOr: if (myArgs.size() == 0) - return FALSE; + return CONST_FALSE; if (myArgs.size() == 1) return myArgs[0]; break; case OpXor: if (myArgs.size() == 0) - return xorRemovedOddTrues ? TRUE : FALSE; + return xorRemovedOddTrues ? CONST_TRUE : CONST_FALSE; if (myArgs.size() == 1) return xorRemovedOddTrues ? NOT(myArgs[0]) : myArgs[0]; break; @@ -161,15 +161,15 @@ int ezSAT::expression(OpId op, const std::vector &args) case OpIFF: assert(myArgs.size() >= 1); if (myArgs.size() == 1) - return TRUE; + return CONST_TRUE; // FIXME: Add proper const folding break; case OpITE: assert(myArgs.size() == 3); - if (myArgs[0] == TRUE) + if (myArgs[0] == CONST_TRUE) return myArgs[1]; - if (myArgs[0] == FALSE) + if (myArgs[0] == CONST_FALSE) return myArgs[2]; break; @@ -281,7 +281,7 @@ std::string ezSAT::to_string(int id) const int ezSAT::eval(int id, const std::vector &values) const { if (id > 0) { - if (id <= int(values.size()) && (values[id-1] == TRUE || values[id-1] == FALSE || values[id-1] == 0)) + if (id <= int(values.size()) && (values[id-1] == CONST_TRUE || values[id-1] == CONST_FALSE || values[id-1] == 0)) return values[id-1]; return 0; } @@ -295,39 +295,39 @@ int ezSAT::eval(int id, const std::vector &values) const case OpNot: assert(args.size() == 1); a = eval(args[0], values); - if (a == TRUE) - return FALSE; - if (a == FALSE) - return TRUE; + if (a == CONST_TRUE) + return CONST_FALSE; + if (a == CONST_FALSE) + return CONST_TRUE; return 0; case OpAnd: - a = TRUE; + a = CONST_TRUE; for (auto arg : args) { b = eval(arg, values); - if (b != TRUE && b != FALSE) + if (b != CONST_TRUE && b != CONST_FALSE) a = 0; - if (b == FALSE) - return FALSE; + if (b == CONST_FALSE) + return CONST_FALSE; } return a; case OpOr: - a = FALSE; + a = CONST_FALSE; for (auto arg : args) { b = eval(arg, values); - if (b != TRUE && b != FALSE) + if (b != CONST_TRUE && b != CONST_FALSE) a = 0; - if (b == TRUE) - return TRUE; + if (b == CONST_TRUE) + return CONST_TRUE; } return a; case OpXor: - a = FALSE; + a = CONST_FALSE; for (auto arg : args) { b = eval(arg, values); - if (b != TRUE && b != FALSE) + if (b != CONST_TRUE && b != CONST_FALSE) return 0; - if (b == TRUE) - a = a == TRUE ? FALSE : TRUE; + if (b == CONST_TRUE) + a = a == CONST_TRUE ? CONST_FALSE : CONST_TRUE; } return a; case OpIFF: @@ -335,18 +335,18 @@ int ezSAT::eval(int id, const std::vector &values) const a = eval(args[0], values); for (auto arg : args) { b = eval(arg, values); - if (b != TRUE && b != FALSE) + if (b != CONST_TRUE && b != CONST_FALSE) return 0; if (b != a) - return FALSE; + return CONST_FALSE; } - return TRUE; + return CONST_TRUE; case OpITE: assert(args.size() == 3); a = eval(args[0], values); - if (a == TRUE) + if (a == CONST_TRUE) return eval(args[1], values); - if (a == FALSE) + if (a == CONST_FALSE) return eval(args[2], values); return 0; default: @@ -516,9 +516,9 @@ int ezSAT::bind(int id, bool auto_freeze) } if (cnfLiteralVariables[id-1] == 0) { cnfLiteralVariables[id-1] = ++cnfVariableCount; - if (id == TRUE) + if (id == CONST_TRUE) add_clause(+cnfLiteralVariables[id-1]); - if (id == FALSE) + if (id == CONST_FALSE) add_clause(-cnfLiteralVariables[id-1]); } return cnfLiteralVariables[id-1]; @@ -638,7 +638,7 @@ std::vector ezSAT::vec_const(const std::vector &bits) { std::vector vec; for (auto bit : bits) - vec.push_back(bit ? TRUE : FALSE); + vec.push_back(bit ? CONST_TRUE : CONST_FALSE); return vec; } @@ -646,7 +646,7 @@ std::vector ezSAT::vec_const_signed(int64_t value, int numBits) { std::vector vec; for (int i = 0; i < numBits; i++) - vec.push_back(((value >> i) & 1) != 0 ? TRUE : FALSE); + vec.push_back(((value >> i) & 1) != 0 ? CONST_TRUE : CONST_FALSE); return vec; } @@ -654,7 +654,7 @@ std::vector ezSAT::vec_const_unsigned(uint64_t value, int numBits) { std::vector vec; for (int i = 0; i < numBits; i++) - vec.push_back(((value >> i) & 1) != 0 ? TRUE : FALSE); + vec.push_back(((value >> i) & 1) != 0 ? CONST_TRUE : CONST_FALSE); return vec; } @@ -679,7 +679,7 @@ std::vector ezSAT::vec_cast(const std::vector &vec1, int toBits, bool std::vector vec; for (int i = 0; i < toBits; i++) if (i >= int(vec1.size())) - vec.push_back(signExtend ? vec1.back() : FALSE); + vec.push_back(signExtend ? vec1.back() : CONST_FALSE); else vec.push_back(vec1[i]); return vec; @@ -807,7 +807,7 @@ std::vector ezSAT::vec_add(const std::vector &vec1, const std::vector< { assert(vec1.size() == vec2.size()); std::vector vec(vec1.size()); - int carry = FALSE; + int carry = CONST_FALSE; for (int i = 0; i < int(vec1.size()); i++) fulladder(this, vec1[i], vec2[i], carry, carry, vec[i]); @@ -831,7 +831,7 @@ std::vector ezSAT::vec_sub(const std::vector &vec1, const std::vector< { assert(vec1.size() == vec2.size()); std::vector vec(vec1.size()); - int carry = TRUE; + int carry = CONST_TRUE; for (int i = 0; i < int(vec1.size()); i++) fulladder(this, vec1[i], NOT(vec2[i]), carry, carry, vec[i]); @@ -853,15 +853,15 @@ std::vector ezSAT::vec_sub(const std::vector &vec1, const std::vector< std::vector ezSAT::vec_neg(const std::vector &vec) { - std::vector zero(vec.size(), FALSE); + std::vector zero(vec.size(), CONST_FALSE); return vec_sub(zero, vec); } void ezSAT::vec_cmp(const std::vector &vec1, const std::vector &vec2, int &carry, int &overflow, int &sign, int &zero) { assert(vec1.size() == vec2.size()); - carry = TRUE; - zero = FALSE; + carry = CONST_TRUE; + zero = CONST_FALSE; for (int i = 0; i < int(vec1.size()); i++) { overflow = carry; fulladder(this, vec1[i], NOT(vec2[i]), carry, carry, sign); @@ -954,11 +954,11 @@ std::vector ezSAT::vec_shl(const std::vector &vec1, int shift, bool si for (int i = 0; i < int(vec1.size()); i++) { int j = i-shift; if (int(vec1.size()) <= j) - vec.push_back(signExtend ? vec1.back() : FALSE); + vec.push_back(signExtend ? vec1.back() : CONST_FALSE); else if (0 <= j) vec.push_back(vec1[j]); else - vec.push_back(FALSE); + vec.push_back(CONST_FALSE); } return vec; } @@ -1005,10 +1005,10 @@ std::vector ezSAT::vec_shift_right(const std::vector &vec1, const std: int vec2_bits = std::min(my_clog2(vec1.size()) + (vec2_signed ? 1 : 0), int(vec2.size())); std::vector overflow_bits(vec2.begin() + vec2_bits, vec2.end()); - int overflow_left = FALSE, overflow_right = FALSE; + int overflow_left = CONST_FALSE, overflow_right = CONST_FALSE; if (vec2_signed) { - int overflow = FALSE; + int overflow = CONST_FALSE; for (auto bit : overflow_bits) overflow = OR(overflow, XOR(bit, vec2[vec2_bits-1])); overflow_left = AND(overflow, NOT(vec2.back())); @@ -1330,7 +1330,7 @@ int ezSAT::manyhot(const std::vector &vec, int min_hot, int max_hot) for (int i = -1; i < N; i++) for (int j = -1; j < M; j++) - x[std::pair(i,j)] = j < 0 ? TRUE : i < 0 ? FALSE : literal(); + x[std::pair(i,j)] = j < 0 ? CONST_TRUE : i < 0 ? CONST_FALSE : literal(); for (int i = 0; i < N; i++) for (int j = 0; j < M; j++) { @@ -1358,7 +1358,7 @@ int ezSAT::manyhot(const std::vector &vec, int min_hot, int max_hot) int ezSAT::ordered(const std::vector &vec1, const std::vector &vec2, bool allow_equal) { std::vector formula; - int last_x = FALSE; + int last_x = CONST_FALSE; assert(vec1.size() == vec2.size()); for (size_t i = 0; i < vec1.size(); i++) @@ -1366,7 +1366,7 @@ int ezSAT::ordered(const std::vector &vec1, const std::vector &vec2, b int a = vec1[i], b = vec2[i]; formula.push_back(OR(NOT(a), b, last_x)); - int next_x = i+1 < vec1.size() ? literal() : allow_equal ? FALSE : TRUE; + int next_x = i+1 < vec1.size() ? literal() : allow_equal ? CONST_FALSE : CONST_TRUE; formula.push_back(OR(a, b, last_x, NOT(next_x))); formula.push_back(OR(NOT(a), NOT(b), last_x, NOT(next_x))); last_x = next_x; diff --git a/libs/ezsat/ezsat.h b/libs/ezsat/ezsat.h index c5ef6b0a2..cac6ff0f7 100644 --- a/libs/ezsat/ezsat.h +++ b/libs/ezsat/ezsat.h @@ -34,7 +34,7 @@ class ezSAT // the number zero is not used as valid token number and is used to encode // unused parameters for the functions. // - // positive numbers are literals, with 1 = TRUE and 2 = FALSE; + // positive numbers are literals, with 1 = CONST_TRUE and 2 = CONST_FALSE; // // negative numbers are non-literal expressions. each expression is represented // by an operator id and a list of expressions (literals or non-literals). @@ -44,8 +44,8 @@ public: OpNot, OpAnd, OpOr, OpXor, OpIFF, OpITE }; - static const int TRUE; - static const int FALSE; + static const int CONST_TRUE; + static const int CONST_FALSE; private: bool flag_keep_cnf; diff --git a/passes/sat/eval.cc b/passes/sat/eval.cc index 875896fcd..7a5a02a9b 100644 --- a/passes/sat/eval.cc +++ b/passes/sat/eval.cc @@ -204,7 +204,7 @@ struct VlogHammerReporter if (y_undef.at(i)) { log(" Toggling undef bit %d to test undef gating.\n", i); - if (!ez.solve(y_vec, y_values, ez.IFF(y_vec.at(i), y_values.at(i) ? ez.FALSE : ez.TRUE))) + if (!ez.solve(y_vec, y_values, ez.IFF(y_vec.at(i), y_values.at(i) ? ez.CONST_FALSE : ez.CONST_TRUE))) log_error("Failed to find solution with toggled bit!\n"); cmp_vars.push_back(y_vec.at(expected_y.size() + i)); From bbd808072be859074a023795a15bebab87cbfba8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 10 Oct 2014 17:22:08 +0200 Subject: [PATCH 019/492] Added format __attribute__ to stringf() --- frontends/verilog/preproc.cc | 2 +- kernel/satgen.h | 2 +- kernel/yosys.h | 2 +- passes/cmds/show.cc | 2 +- passes/techmap/techmap.cc | 6 ++++-- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index f83433219..7e14fcb84 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -422,7 +422,7 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons if (tok == "(" || tok == "{" || tok == "[") level++; } - for (size_t i = 0; i < args.size(); i++) + for (int i = 0; i < GetSize(args); i++) defines_map[stringf("macro_%s_arg%d", name.c_str(), i+1)] = args[i]; } else { insert_input(tok); diff --git a/kernel/satgen.h b/kernel/satgen.h index 779c97506..d556f4f32 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -68,7 +68,7 @@ struct SatGen else vec.push_back(bit == (undef_mode ? RTLIL::State::Sx : RTLIL::State::S1) ? ez->CONST_TRUE : ez->CONST_FALSE); } else { - std::string name = pf + stringf(bit.wire->width == 1 ? "%s" : "%s [%d]", RTLIL::id2cstr(bit.wire->name), bit.offset); + std::string name = pf + (bit.wire->width == 1 ? stringf("%s", log_id(bit.wire)) : stringf("%s [%d]", log_id(bit.wire->name), bit.offset)); vec.push_back(ez->frozen_literal(name)); imported_signals[pf][bit] = vec.back(); } diff --git a/kernel/yosys.h b/kernel/yosys.h index c5da9f046..d3f885644 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -82,7 +82,7 @@ namespace RTLIL { struct Cell; } -std::string stringf(const char *fmt, ...); +std::string stringf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); std::string vstringf(const char *fmt, va_list ap); template int GetSize(const T &obj) { return obj.size(); } int GetSize(RTLIL::Wire *wire); diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index abe6cd460..1599879a1 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -72,7 +72,7 @@ struct ShowWorker { if (currentColor == 0) return "color=\"black\""; - return stringf("colorscheme=\"dark28\", color=\"%d\", fontcolor=\"%d\"", currentColor%8+1); + return stringf("colorscheme=\"dark28\", color=\"%d\", fontcolor=\"%d\"", currentColor%8+1, currentColor%8+1); } std::string nextColor(std::string presetColor) diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 0ee45ba39..73da6ce1d 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -109,8 +109,10 @@ struct TechmapWorker connbits_map.at(bit).second, log_id(connbits_map.at(bit).first)); constmap_info += stringf("|%s %d %s %d", log_id(conn.first), i, log_id(connbits_map.at(bit).first), connbits_map.at(bit).second); - } else - connbits_map[bit] = std::pair(conn.first, i);stringf("%s %d", log_id(conn.first), i, bit.data); + } else { + connbits_map[bit] = std::pair(conn.first, i); + constmap_info += stringf("|%s %d", log_id(conn.first), i); + } } return stringf("$paramod$constmap:%s%s", sha1(constmap_info).c_str(), tpl->name.c_str()); From 774933a0d88502585cf8c169280e71d0c3d182fc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 10 Oct 2014 18:02:17 +0200 Subject: [PATCH 020/492] Replaced fnmatch() with patmatch() --- kernel/patmatch.h | 91 +++++++++++++++++++++++++++++++++++ passes/cmds/cover.cc | 8 ++- passes/cmds/select.cc | 15 +++--- passes/hierarchy/hierarchy.cc | 9 ++-- 4 files changed, 105 insertions(+), 18 deletions(-) create mode 100644 kernel/patmatch.h diff --git a/kernel/patmatch.h b/kernel/patmatch.h new file mode 100644 index 000000000..611c8d86e --- /dev/null +++ b/kernel/patmatch.h @@ -0,0 +1,91 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef PATMATCH_H +#define PATMATCH_H + +#include "kernel/yosys.h" + +YOSYS_NAMESPACE_BEGIN + +// this is very similar to fnmatch(). the exact rules used by this +// function are: +// +// ? matches any character except +// * matches any sequence of characters +// [...] matches any of the characters in the list +// [!..] matches any of the characters not in the list +// +// a backslash may be used to escape the next characters in the +// pattern. each special character can also simply match itself. +// +static bool patmatch(const char *pattern, const char *string) +{ + if (*pattern == 0) + return *string == 0; + + if (*pattern == '\\') { + if (pattern[1] == string[0] && patmatch(pattern+2, string+1)) + return true; + } + + if (*pattern == '?') { + if (*string == 0) + return false; + return patmatch(pattern+1, string+1); + } + + if (*pattern == '*') { + while (*string) { + if (patmatch(pattern+1, string++)) + return true; + } + return pattern[1] == 0; + } + + if (*pattern == '[') { + bool found_match = false; + bool inverted_list = pattern[1] == '!'; + const char *p = pattern + (inverted_list ? 1 : 0); + + while (*++p) { + if (*p == ']') { + if (found_match != inverted_list && patmatch(p+1, string+1)) + return true; + break; + } + + if (*p == '\\') { + if (*++p == *string) + found_match = true; + } else + if (*p == *string) + found_match = true; + } + } + + if (*pattern == *string) + return patmatch(pattern+1, string+1); + + return false; +} + +YOSYS_NAMESPACE_END + +#endif diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc index 057f31217..64f7acf50 100644 --- a/passes/cmds/cover.cc +++ b/passes/cmds/cover.cc @@ -19,11 +19,9 @@ #include #include -#include -#include "kernel/register.h" -#include "kernel/rtlil.h" -#include "kernel/log.h" +#include "kernel/yosys.h" +#include "kernel/patmatch.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -123,7 +121,7 @@ struct CoverPass : public Pass { for (auto &it : get_coverage_data()) { if (!patterns.empty()) { for (auto &p : patterns) - if (!fnmatch(p.c_str(), it.first.c_str(), 0)) + if (patmatch(p.c_str(), it.first.c_str())) goto pattern_match; continue; } diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 363687f25..893f897d2 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -17,12 +17,11 @@ * */ -#include "kernel/register.h" +#include "kernel/yosys.h" #include "kernel/celltypes.h" #include "kernel/sigtools.h" -#include "kernel/log.h" +#include "kernel/patmatch.h" #include -#include #include USING_YOSYS_NAMESPACE @@ -38,9 +37,9 @@ static bool match_ids(RTLIL::IdString id, std::string pattern) return true; if (id.size() > 0 && id[0] == '\\' && id.substr(1) == pattern) return true; - if (!fnmatch(pattern.c_str(), id.c_str(), 0)) + if (patmatch(pattern.c_str(), id.c_str())) return true; - if (id.size() > 0 && id[0] == '\\' && !fnmatch(pattern.c_str(), id.substr(1).c_str(), 0)) + if (id.size() > 0 && id[0] == '\\' && patmatch(pattern.c_str(), id.substr(1).c_str())) return true; if (id.size() > 0 && id[0] == '$' && pattern.size() > 0 && pattern[0] == '$') { const char *p = id.c_str(); @@ -83,7 +82,7 @@ static bool match_attr_val(const RTLIL::Const &value, std::string pattern, char std::string value_str = value.decode_string(); if (match_op == '=') - if (!fnmatch(pattern.c_str(), value.decode_string().c_str(), FNM_NOESCAPE)) + if (patmatch(pattern.c_str(), value.decode_string().c_str())) return true; if (match_op == '=') @@ -107,9 +106,9 @@ static bool match_attr(const std::map &attributes { if (name_pat.find('*') != std::string::npos || name_pat.find('?') != std::string::npos || name_pat.find('[') != std::string::npos) { for (auto &it : attributes) { - if (!fnmatch(name_pat.c_str(), it.first.c_str(), FNM_NOESCAPE) && match_attr_val(it.second, value_pat, match_op)) + if (patmatch(name_pat.c_str(), it.first.c_str()) && match_attr_val(it.second, value_pat, match_op)) return true; - if (it.first.size() > 0 && it.first[0] == '\\' && !fnmatch(name_pat.c_str(), it.first.substr(1).c_str(), FNM_NOESCAPE) && match_attr_val(it.second, value_pat, match_op)) + if (it.first.size() > 0 && it.first[0] == '\\' && patmatch(name_pat.c_str(), it.first.substr(1).c_str()) && match_attr_val(it.second, value_pat, match_op)) return true; } } else { diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 960fc1929..68317a60a 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -17,11 +17,10 @@ * */ -#include "kernel/register.h" -#include "kernel/log.h" +#include "kernel/yosys.h" +#include "kernel/patmatch.h" #include #include -#include #include #include @@ -47,7 +46,7 @@ void generate(RTLIL::Design *design, const std::vector &celltypes, if (cell->type.substr(0, 1) == "$" && cell->type.substr(0, 3) != "$__") continue; for (auto &pattern : celltypes) - if (!fnmatch(pattern.c_str(), RTLIL::unescape_id(cell->type).c_str(), FNM_NOESCAPE)) + if (patmatch(pattern.c_str(), RTLIL::unescape_id(cell->type).c_str())) found_celltypes.insert(cell->type); } @@ -97,7 +96,7 @@ void generate(RTLIL::Design *design, const std::vector &celltypes, while (portnames.size() > 0) { RTLIL::IdString portname = *portnames.begin(); for (auto &decl : portdecls) - if (decl.index == 0 && !fnmatch(decl.portname.c_str(), RTLIL::unescape_id(portname).c_str(), FNM_NOESCAPE)) { + if (decl.index == 0 && patmatch(decl.portname.c_str(), RTLIL::unescape_id(portname).c_str())) { generate_port_decl_t d = decl; d.portname = portname; d.index = *indices.begin(); From ee5165c6e470d0f66e339ff796b074f8ac1a89aa Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 10 Oct 2014 18:19:00 +0200 Subject: [PATCH 021/492] Moved patmatch() to yosys.cc --- kernel/patmatch.h | 91 ----------------------------------- kernel/yosys.cc | 62 ++++++++++++++++++++++++ kernel/yosys.h | 3 ++ passes/cmds/cover.cc | 2 - passes/cmds/select.cc | 1 - passes/hierarchy/hierarchy.cc | 1 - 6 files changed, 65 insertions(+), 95 deletions(-) delete mode 100644 kernel/patmatch.h diff --git a/kernel/patmatch.h b/kernel/patmatch.h deleted file mode 100644 index 611c8d86e..000000000 --- a/kernel/patmatch.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#ifndef PATMATCH_H -#define PATMATCH_H - -#include "kernel/yosys.h" - -YOSYS_NAMESPACE_BEGIN - -// this is very similar to fnmatch(). the exact rules used by this -// function are: -// -// ? matches any character except -// * matches any sequence of characters -// [...] matches any of the characters in the list -// [!..] matches any of the characters not in the list -// -// a backslash may be used to escape the next characters in the -// pattern. each special character can also simply match itself. -// -static bool patmatch(const char *pattern, const char *string) -{ - if (*pattern == 0) - return *string == 0; - - if (*pattern == '\\') { - if (pattern[1] == string[0] && patmatch(pattern+2, string+1)) - return true; - } - - if (*pattern == '?') { - if (*string == 0) - return false; - return patmatch(pattern+1, string+1); - } - - if (*pattern == '*') { - while (*string) { - if (patmatch(pattern+1, string++)) - return true; - } - return pattern[1] == 0; - } - - if (*pattern == '[') { - bool found_match = false; - bool inverted_list = pattern[1] == '!'; - const char *p = pattern + (inverted_list ? 1 : 0); - - while (*++p) { - if (*p == ']') { - if (found_match != inverted_list && patmatch(p+1, string+1)) - return true; - break; - } - - if (*p == '\\') { - if (*++p == *string) - found_match = true; - } else - if (*p == *string) - found_match = true; - } - } - - if (*pattern == *string) - return patmatch(pattern+1, string+1); - - return false; -} - -YOSYS_NAMESPACE_END - -#endif diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 971da78ab..d728329e3 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -66,6 +66,68 @@ std::string vstringf(const char *fmt, va_list ap) return string; } +// this is very similar to fnmatch(). the exact rules used by this +// function are: +// +// ? matches any character except +// * matches any sequence of characters +// [...] matches any of the characters in the list +// [!..] matches any of the characters not in the list +// +// a backslash may be used to escape the next characters in the +// pattern. each special character can also simply match itself. +// +static bool patmatch(const char *pattern, const char *string) +{ + if (*pattern == 0) + return *string == 0; + + if (*pattern == '\\') { + if (pattern[1] == string[0] && patmatch(pattern+2, string+1)) + return true; + } + + if (*pattern == '?') { + if (*string == 0) + return false; + return patmatch(pattern+1, string+1); + } + + if (*pattern == '*') { + while (*string) { + if (patmatch(pattern+1, string++)) + return true; + } + return pattern[1] == 0; + } + + if (*pattern == '[') { + bool found_match = false; + bool inverted_list = pattern[1] == '!'; + const char *p = pattern + (inverted_list ? 1 : 0); + + while (*++p) { + if (*p == ']') { + if (found_match != inverted_list && patmatch(p+1, string+1)) + return true; + break; + } + + if (*p == '\\') { + if (*++p == *string) + found_match = true; + } else + if (*p == *string) + found_match = true; + } + } + + if (*pattern == *string) + return patmatch(pattern+1, string+1); + + return false; +} + int GetSize(RTLIL::Wire *wire) { return wire->width; diff --git a/kernel/yosys.h b/kernel/yosys.h index d3f885644..a796dd09f 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -84,6 +84,9 @@ namespace RTLIL { std::string stringf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); std::string vstringf(const char *fmt, va_list ap); + +bool patmatch(const char *pattern, const char *string); + template int GetSize(const T &obj) { return obj.size(); } int GetSize(RTLIL::Wire *wire); diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc index 64f7acf50..b8792a05f 100644 --- a/passes/cmds/cover.cc +++ b/passes/cmds/cover.cc @@ -19,9 +19,7 @@ #include #include - #include "kernel/yosys.h" -#include "kernel/patmatch.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 893f897d2..af0df07b3 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -20,7 +20,6 @@ #include "kernel/yosys.h" #include "kernel/celltypes.h" #include "kernel/sigtools.h" -#include "kernel/patmatch.h" #include #include diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 68317a60a..87d115027 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -18,7 +18,6 @@ */ #include "kernel/yosys.h" -#include "kernel/patmatch.h" #include #include #include From 986bcc13cbe6a085aa826e87f9d56bde22c7e521 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 10 Oct 2014 18:19:18 +0200 Subject: [PATCH 022/492] Various win32 build fixes in yosys.cc --- kernel/yosys.cc | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index d728329e3..7272c073b 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -24,7 +24,10 @@ # include #endif -#include +#ifndef _WIN32 +# include +#endif + #include #include #include @@ -55,8 +58,22 @@ std::string vstringf(const char *fmt, va_list ap) std::string string; char *str = NULL; +#ifdef _WIN32 + int sz = 64, rc; + while (1) { + va_list apc; + va_copy(apc, ap); + str = (char*)realloc(str, sz); + rc = vsnprintf(str, sz, fmt, apc); + va_end(apc); + if (rc >= 0 && rc < sz) + break; + sz *= 2; + } +#else if (vasprintf(&str, fmt, ap) < 0) str = NULL; +#endif if (str != NULL) { string = str; @@ -163,8 +180,10 @@ void yosys_shutdown() } #endif +#ifndef _WIN32 for (auto &it : loaded_plugins) dlclose(it.second); +#endif loaded_plugins.clear(); loaded_plugin_aliases.clear(); @@ -272,7 +291,7 @@ struct TclPass : public Pass { #endif #if defined(__linux__) -std::string proc_self_dirname () +std::string proc_self_dirname() { char path [PATH_MAX]; ssize_t buflen = readlink("/proc/self/exe", path, sizeof(path)); @@ -285,7 +304,7 @@ std::string proc_self_dirname () } #elif defined(__APPLE__) #include -std::string proc_self_dirname () +std::string proc_self_dirname() { char * path = NULL; uint32_t buflen = 0; @@ -295,8 +314,14 @@ std::string proc_self_dirname () buflen--; return std::string(path, buflen); } +#elif defined(_WIN32) +std::string proc_self_dirname() +{ + #warning Fixme: Implement proc_self_dirname() for win32. + log_error("proc_self_dirname() is not implemented for win32 yet!\n"); +} #elif defined(EMSCRIPTEN) -std::string proc_self_dirname () +std::string proc_self_dirname() { return "/"; } @@ -304,7 +329,7 @@ std::string proc_self_dirname () #error Dont know how to determine process executable base path! #endif -std::string proc_share_dirname () +std::string proc_share_dirname() { std::string proc_self_path = proc_self_dirname(); std::string proc_share_path = proc_self_path + "share/"; From 2c683102be85b0ee9c03c85ddcf5d7fd0f004ab7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 10 Oct 2014 18:33:55 +0200 Subject: [PATCH 023/492] Added next_token() function (strtok() replacement) --- kernel/yosys.cc | 19 ++++++++++++++++++- kernel/yosys.h | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 7272c073b..96fe5446d 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -83,6 +83,23 @@ std::string vstringf(const char *fmt, va_list ap) return string; } +std::string next_token(std::string &text, const char *sep) +{ + size_t pos_begin = text.find_first_not_of(sep); + + if (pos_begin == string::npos) + pos_begin = text.size(); + + size_t pos_end = text.find_first_of(sep, pos_begin); + + if (pos_end == string::npos) + pos_end = text.size(); + + std::string token = text.substr(pos_begin, pos_end-pos_begin); + text = text.substr(pos_end); + return token; +} + // this is very similar to fnmatch(). the exact rules used by this // function are: // @@ -94,7 +111,7 @@ std::string vstringf(const char *fmt, va_list ap) // a backslash may be used to escape the next characters in the // pattern. each special character can also simply match itself. // -static bool patmatch(const char *pattern, const char *string) +bool patmatch(const char *pattern, const char *string) { if (*pattern == 0) return *string == 0; diff --git a/kernel/yosys.h b/kernel/yosys.h index a796dd09f..919e3bb98 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -84,7 +84,7 @@ namespace RTLIL { std::string stringf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); std::string vstringf(const char *fmt, va_list ap); - +std::string next_token(std::string &text, const char *sep); bool patmatch(const char *pattern, const char *string); template int GetSize(const T &obj) { return obj.size(); } From 54bf3a95dd859ac1811a5265ad45f9eb596de3db Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 10 Oct 2014 18:34:19 +0200 Subject: [PATCH 024/492] More Win32 build fixes --- libs/subcircuit/subcircuit.cc | 4 ++++ passes/techmap/extract.cc | 17 +++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/libs/subcircuit/subcircuit.cc b/libs/subcircuit/subcircuit.cc index 84f23d636..cf14df0ac 100644 --- a/libs/subcircuit/subcircuit.cc +++ b/libs/subcircuit/subcircuit.cc @@ -34,6 +34,7 @@ using namespace SubCircuit; +#ifndef _YOSYS_ static std::string my_stringf(const char *fmt, ...) { std::string string; @@ -52,6 +53,9 @@ static std::string my_stringf(const char *fmt, ...) return string; } +#else +# define my_stringf YOSYS_NAMESPACE_PREFIX stringf +#endif SubCircuit::Graph::Graph(const Graph &other, const std::vector &otherNodes) { diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc index e0b1d360a..994ef8f2a 100644 --- a/passes/techmap/extract.cc +++ b/passes/techmap/extract.cc @@ -518,24 +518,21 @@ struct ExtractPass : public Pass { if (args[argidx] == "-swap" && argidx+2 < args.size()) { std::string type = RTLIL::escape_id(args[++argidx]); std::set ports; - char *ports_str = strdup(args[++argidx].c_str()); - for (char *sptr, *p = strtok_r(ports_str, ",\t\r\n ", &sptr); p != NULL; p = strtok_r(NULL, ",\t\r\n ", &sptr)) + std::string ports_str = args[++argidx], p; + while (!(p = next_token(ports_str, ",\t\r\n ")).empty()) ports.insert(RTLIL::escape_id(p)); - free(ports_str); solver.addSwappablePorts(type, ports); continue; } if (args[argidx] == "-perm" && argidx+3 < args.size()) { std::string type = RTLIL::escape_id(args[++argidx]); std::vector map_left, map_right; - char *left_str = strdup(args[++argidx].c_str()); - char *right_str = strdup(args[++argidx].c_str()); - for (char *sptr, *p = strtok_r(left_str, ",\t\r\n ", &sptr); p != NULL; p = strtok_r(NULL, ",\t\r\n ", &sptr)) + std::string left_str = args[++argidx]; + std::string right_str = args[++argidx], p; + while (!(p = next_token(left_str, ",\t\r\n ")).empty()) map_left.push_back(RTLIL::escape_id(p)); - for (char *sptr, *p = strtok_r(right_str, ",\t\r\n ", &sptr); p != NULL; p = strtok_r(NULL, ",\t\r\n ", &sptr)) + while (!(p = next_token(right_str, ",\t\r\n ")).empty()) map_right.push_back(RTLIL::escape_id(p)); - free(left_str); - free(right_str); if (map_left.size() != map_right.size()) log_cmd_error("Arguments to -perm are not a valid permutation!\n"); std::map map; @@ -665,7 +662,7 @@ struct ExtractPass : public Pass { log("Solving for %s in %s.\n", ("needle_" + RTLIL::unescape_id(needle->name)).c_str(), haystack_it.first.c_str()); solver.solve(results, "needle_" + RTLIL::unescape_id(needle->name), haystack_it.first, false); } - log("Found %zd matches.\n", results.size()); + log("Found %d matches.\n", GetSize(results)); if (results.size() > 0) { From 20d85f20dbb16a1c47f7993da06f5b9abac1d09d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 10 Oct 2014 18:38:40 +0200 Subject: [PATCH 025/492] Fixed next_token() --- kernel/yosys.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 96fe5446d..08f75df7b 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -87,12 +87,12 @@ std::string next_token(std::string &text, const char *sep) { size_t pos_begin = text.find_first_not_of(sep); - if (pos_begin == string::npos) + if (pos_begin == std::string::npos) pos_begin = text.size(); size_t pos_end = text.find_first_of(sep, pos_begin); - if (pos_end == string::npos) + if (pos_end == std::string::npos) pos_end = text.size(); std::string token = text.substr(pos_begin, pos_end-pos_begin); From df537a216ba6a954a7b3e5631d35f58ebe3b2c0e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 10 Oct 2014 18:53:03 +0200 Subject: [PATCH 026/492] Using next_token() to parse commands --- kernel/register.cc | 48 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/kernel/register.cc b/kernel/register.cc index 2f7b89ffd..9452eb355 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -146,35 +146,34 @@ void Pass::extra_args(std::vector args, size_t argidx, RTLIL::Desig void Pass::call(RTLIL::Design *design, std::string command) { std::vector args; - char *s = strdup(command.c_str()), *sstart = s, *saveptr; - s += strspn(s, " \t\r\n"); - if (*s == 0 || *s == '#') { - free(sstart); + + std::string cmd_buf = command; + std::string tok = next_token(cmd_buf, " \t\r\n"); + + if (tok.empty() || tok[0] == '#') return; - } - if (*s == '!') { - for (s++; *s == ' ' || *s == '\t'; s++) { } - char *p = s + strlen(s) - 1; - while (p >= s && (*p == '\r' || *p == '\n')) - *(p--) = 0; - log_header("Shell command: %s\n", s); - int retCode = system(s); + + if (tok[0] == '!') { + cmd_buf = command.substr(command.find('!') + 1); + while (!cmd_buf.empty() && (cmd_buf.back() == ' ' || cmd_buf.back() == '\t' || + cmd_buf.back() == '\r' || cmd_buf.back() == '\n')) + cmd_buf.resize(cmd_buf.size()-1); + log_header("Shell command: %s\n", cmd_buf.c_str()); + int retCode = system(cmd_buf.c_str()); if (retCode != 0) log_cmd_error("Shell command returned error code %d.\n", retCode); - free(sstart); return; } - for (char *p = strtok_r(s, " \t\r\n", &saveptr); p; p = strtok_r(NULL, " \t\r\n", &saveptr)) { - std::string str = p; - int strsz = str.size(); - if (str == "#") + + while (!tok.empty()) { + if (tok == "#") break; - if (strsz > 0 && str[strsz-1] == ';') { + if (tok.back() == ';') { int num_semikolon = 0; - while (strsz > 0 && str[strsz-1] == ';') - strsz--, num_semikolon++; - if (strsz > 0) - args.push_back(str.substr(0, strsz)); + while (!tok.empty() && tok.back() == ';') + tok.resize(tok.size()-1), num_semikolon++; + if (!tok.empty()) + args.push_back(tok); call(design, args); args.clear(); if (num_semikolon == 2) @@ -182,9 +181,10 @@ void Pass::call(RTLIL::Design *design, std::string command) if (num_semikolon == 3) call(design, "clean -purge"); } else - args.push_back(str); + args.push_back(tok); + tok = next_token(cmd_buf, " \t\r\n"); } - free(sstart); + call(design, args); } From 93e6ebe771c675280742adf6905298301575d0a7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 Oct 2014 10:24:46 +0200 Subject: [PATCH 027/492] Disabled ezminisat timeout feature for Win32 --- libs/ezsat/ezminisat.cc | 6 ++++++ libs/ezsat/ezminisat.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/libs/ezsat/ezminisat.cc b/libs/ezsat/ezminisat.cc index 267355ada..b996d4a3d 100644 --- a/libs/ezsat/ezminisat.cc +++ b/libs/ezsat/ezminisat.cc @@ -77,6 +77,7 @@ bool ezMiniSAT::eliminated(int idx) } #endif +#ifndef _WIN32 ezMiniSAT *ezMiniSAT::alarmHandlerThis = NULL; clock_t ezMiniSAT::alarmHandlerTimeout = 0; @@ -88,6 +89,7 @@ void ezMiniSAT::alarmHandler(int) } else alarm(1); } +#endif bool ezMiniSAT::solver(const std::vector &modelExpressions, std::vector &modelValues, const std::vector &assumptions) { @@ -174,6 +176,7 @@ contradiction: #endif } +#ifndef _WIN32 struct sigaction sig_action; struct sigaction old_sig_action; int old_alarm_timeout = 0; @@ -188,9 +191,11 @@ contradiction: sigaction(SIGALRM, &sig_action, &old_sig_action); alarm(1); } +#endif bool foundSolution = minisatSolver->solve(assumps); +#ifndef _WIN32 if (solverTimeout > 0) { if (alarmHandlerTimeout == 0) solverTimoutStatus = true; @@ -198,6 +203,7 @@ contradiction: sigaction(SIGALRM, &old_sig_action, NULL); alarm(old_alarm_timeout); } +#endif if (!foundSolution) { #if !EZMINISAT_INCREMENTAL diff --git a/libs/ezsat/ezminisat.h b/libs/ezsat/ezminisat.h index ac9c071c3..5b5252d88 100644 --- a/libs/ezsat/ezminisat.h +++ b/libs/ezsat/ezminisat.h @@ -51,9 +51,11 @@ private: std::set cnfFrozenVars; #endif +#ifndef _WIN32 static ezMiniSAT *alarmHandlerThis; static clock_t alarmHandlerTimeout; static void alarmHandler(int); +#endif public: ezMiniSAT(); From 0a651f112fe62fdf86e4b288988a9ed9ac90068d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 Oct 2014 10:46:19 +0200 Subject: [PATCH 028/492] Disabled vhdl2verilog command for win32 builds --- frontends/vhdl2verilog/vhdl2verilog.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontends/vhdl2verilog/vhdl2verilog.cc b/frontends/vhdl2verilog/vhdl2verilog.cc index b408d621b..a8c411c7b 100644 --- a/frontends/vhdl2verilog/vhdl2verilog.cc +++ b/frontends/vhdl2verilog/vhdl2verilog.cc @@ -120,6 +120,10 @@ struct Vhdl2verilogPass : public Pass { if (top_entity.empty()) log_cmd_error("Missing -top option.\n"); +#ifdef _WIN32 + #warning Fixme: The vhdl2veriog command has not been ported to win32. + log_cmd_error("The vhdl2veriog command has not been ported to win32.\n"); +#else char tempdir_name[] = "/tmp/yosys-vhdl2verilog-XXXXXX"; char *p = mkdtemp(tempdir_name); log("Using temp directory %s.\n", tempdir_name); @@ -189,6 +193,7 @@ struct Vhdl2verilogPass : public Pass { log_error("Execution of \"rm -rf '%s'\" failed!\n", tempdir_name); log_pop(); +#endif } } Vhdl2verilogPass; From 7df8cbe2a9d48dbccb4a2c665e4087ed4f1514a8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 Oct 2014 10:46:50 +0200 Subject: [PATCH 029/492] Not using std::to_string in ezsat (problems with mingw) --- libs/ezsat/ezsat.cc | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/libs/ezsat/ezsat.cc b/libs/ezsat/ezsat.cc index 754691f7b..54a6e9c71 100644 --- a/libs/ezsat/ezsat.cc +++ b/libs/ezsat/ezsat.cc @@ -669,8 +669,11 @@ std::vector ezSAT::vec_var(int numBits) std::vector ezSAT::vec_var(std::string name, int numBits) { std::vector vec; - for (int i = 0; i < numBits; i++) - vec.push_back(VAR(name + "[" + std::to_string(i) + "]")); + for (int i = 0; i < numBits; i++) { + char buf[64]; + snprintf(buf, 64, " [%d]", i); + vec.push_back(VAR(name + buf)); + } return vec; } @@ -1195,7 +1198,7 @@ void ezSAT::printDIMACS(FILE *f, bool verbose) const fprintf(f, "c mapping of variables to expressions:\n"); for (int i = 0; i < int(cnfExpressionVariables.size()); i++) if (cnfExpressionVariables[i] != 0) - fprintf(f, "c %*d: %s\n", digits, cnfExpressionVariables[i], to_string(-i-1).c_str()); + fprintf(f, "c %*d: %d\n", digits, cnfExpressionVariables[i], -i-1); if (mode_keep_cnf()) { fprintf(f, "c\n"); @@ -1242,8 +1245,11 @@ static std::string expression2str(const std::pair> #undef X } text += ":"; - for (auto it : data.second) - text += " " + std::to_string(it); + for (auto it : data.second) { + char buf[64]; + snprintf(buf, 64, " %d", it); + text += buf; + } return text; } From 51b1824979ab0dc1c1cc904abe85bf39e537e136 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 Oct 2014 10:49:43 +0200 Subject: [PATCH 030/492] Disabled "cover -d" on win32 --- passes/cmds/cover.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc index b8792a05f..857d5aa47 100644 --- a/passes/cmds/cover.cc +++ b/passes/cmds/cover.cc @@ -91,9 +91,13 @@ struct CoverPass : public Pass { const char *open_mode = args[argidx] == "-a" ? "a+" : "w"; std::string filename = args[++argidx]; if (args[argidx-1] == "-d") { + #ifdef _WIN32 + log_cmd_error("The 'cover -d' option is not supported on win32.\n"); + #else char filename_buffer[4096]; snprintf(filename_buffer, 4096, "%s/yosys_cover_%d_XXXXXX.txt", filename.c_str(), getpid()); filename = mkstemps(filename_buffer, 4); + #endif } FILE *f = fopen(filename.c_str(), open_mode); if (f == NULL) { From 53349fb634e79641a7a728f6d030c5eda0702477 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 Oct 2014 10:57:46 +0200 Subject: [PATCH 031/492] Fixed ifdefs for plugin unloading --- kernel/yosys.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 08f75df7b..f2492555e 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -24,7 +24,7 @@ # include #endif -#ifndef _WIN32 +#ifdef YOSYS_ENABLE_PLUGINS # include #endif @@ -197,7 +197,7 @@ void yosys_shutdown() } #endif -#ifndef _WIN32 +#ifdef YOSYS_ENABLE_PLUGINS for (auto &it : loaded_plugins) dlclose(it.second); #endif From e8c66ee36bdbaa9652a4e838cabeff4107f50da1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 Oct 2014 10:59:11 +0200 Subject: [PATCH 032/492] Fixed MXE readline support --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6faeeb4ce..6b77d854b 100644 --- a/Makefile +++ b/Makefile @@ -102,6 +102,9 @@ endif ifeq ($(ENABLE_READLINE),1) CXXFLAGS += -DYOSYS_ENABLE_READLINE LDLIBS += -lreadline +ifeq ($(CONFIG),mxe) +LDLIBS += -lpdcurses +endif endif ifeq ($(ENABLE_PLUGINS),1) @@ -330,7 +333,6 @@ config-mxe: clean echo 'ENABLE_TCL := 0' >> Makefile.conf echo 'ENABLE_ABC := 0' >> Makefile.conf echo 'ENABLE_PLUGINS := 0' >> Makefile.conf - echo 'ENABLE_READLINE := 0' >> Makefile.conf config-gprof: clean echo 'CONFIG := gcc' > Makefile.conf From 568fee5e74093838121ea61ec15d98a111306bba Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 Oct 2014 11:08:52 +0200 Subject: [PATCH 033/492] Added proc_self_dirname() for win32 --- kernel/yosys.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index f2492555e..921f2b383 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -28,6 +28,10 @@ # include #endif +#ifdef _WIN32 +# include +#endif + #include #include #include @@ -310,7 +314,7 @@ struct TclPass : public Pass { #if defined(__linux__) std::string proc_self_dirname() { - char path [PATH_MAX]; + char path[PATH_MAX]; ssize_t buflen = readlink("/proc/self/exe", path, sizeof(path)); if (buflen < 0) { log_error("readlink(\"/proc/self/exe\") failed: %s\n", strerror(errno)); @@ -323,7 +327,7 @@ std::string proc_self_dirname() #include std::string proc_self_dirname() { - char * path = NULL; + char *path = NULL; uint32_t buflen = 0; while (_NSGetExecutablePath(path, &buflen) != 0) path = (char *) realloc((void *) path, buflen); @@ -334,8 +338,12 @@ std::string proc_self_dirname() #elif defined(_WIN32) std::string proc_self_dirname() { - #warning Fixme: Implement proc_self_dirname() for win32. - log_error("proc_self_dirname() is not implemented for win32 yet!\n"); + char path[MAX_PATH+1]; + if (!GetModuleFileName(0, path, MAX_PATH+1)) + log_error("GetModuleFileName() failed.\n"); + for (int i = strlen(path)-1; i >= 0 && path[i] != '/' && path[i] != '\\' ; i--) + path[i] = 0; + return std::string(path); } #elif defined(EMSCRIPTEN) std::string proc_self_dirname() From a32e067e5c96bacc1f0280f9f1bfd979af2171db Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 Oct 2014 11:35:54 +0200 Subject: [PATCH 034/492] Strip win32 executeables --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6b77d854b..8a4ff52e8 100644 --- a/Makefile +++ b/Makefile @@ -91,7 +91,7 @@ else ifeq ($(CONFIG),mxe) CXX = /usr/local/src/mxe/usr/bin/i686-pc-mingw32-gcc CXXFLAGS += -std=gnu++0x -Os -D_POSIX_SOURCE CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS)) -LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) +LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s LDLIBS := $(filter-out -lrt,$(LDLIBS)) EXE = .exe From 8263f6a74a822579f3c1da7d8b128ea8ab7b4d79 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 Oct 2014 11:36:22 +0200 Subject: [PATCH 035/492] Fixed win32 troubles with f.readsome() --- frontends/ilang/lexer.l | 2 +- frontends/verilog/lexer.l | 2 +- frontends/verilog/preproc.cc | 2 +- kernel/yosys.cc | 16 ++++++++++++++++ kernel/yosys.h | 1 + passes/cmds/write_file.cc | 2 +- 6 files changed, 21 insertions(+), 4 deletions(-) diff --git a/frontends/ilang/lexer.l b/frontends/ilang/lexer.l index 292321e88..9669f0924 100644 --- a/frontends/ilang/lexer.l +++ b/frontends/ilang/lexer.l @@ -35,7 +35,7 @@ USING_YOSYS_NAMESPACE #define YY_INPUT(buf,result,max_size) \ - result = ILANG_FRONTEND::lexin->readsome(buf, max_size); + result = readsome(*ILANG_FRONTEND::lexin, buf, max_size); %} diff --git a/frontends/verilog/lexer.l b/frontends/verilog/lexer.l index c9302aba8..98f360885 100644 --- a/frontends/verilog/lexer.l +++ b/frontends/verilog/lexer.l @@ -64,7 +64,7 @@ YOSYS_NAMESPACE_END return TOK_ID; #define YY_INPUT(buf,result,max_size) \ - result = lexin->readsome(buf, max_size); + result = readsome(*lexin, buf, max_size); %} diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index 7e14fcb84..b4e77c31b 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -202,7 +202,7 @@ static void input_file(std::istream &f, std::string filename) auto it = input_buffer.begin(); input_buffer.insert(it, "`file_push " + filename + "\n"); - while ((rc = f.readsome(buffer, sizeof(buffer)-1)) > 0) { + while ((rc = readsome(f, buffer, sizeof(buffer)-1)) > 0) { buffer[rc] = 0; input_buffer.insert(it, buffer); } diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 921f2b383..a40ad4372 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -166,6 +166,22 @@ bool patmatch(const char *pattern, const char *string) return false; } +int readsome(std::istream &f, char *s, int n) +{ + int rc = f.readsome(s, n); + + // win32 sometimes returns 0 on a non-empty stream.. + if (rc == 0) { + int c = f.get(); + if (c != EOF) { + *s = c; + rc = 1; + } + } + + return rc; +} + int GetSize(RTLIL::Wire *wire) { return wire->width; diff --git a/kernel/yosys.h b/kernel/yosys.h index 919e3bb98..d38e60ceb 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -86,6 +86,7 @@ std::string stringf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)) std::string vstringf(const char *fmt, va_list ap); std::string next_token(std::string &text, const char *sep); bool patmatch(const char *pattern, const char *string); +int readsome(std::istream &f, char *s, int n); template int GetSize(const T &obj) { return obj.size(); } int GetSize(RTLIL::Wire *wire); diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc index 9f22861a5..3f4419724 100644 --- a/passes/cmds/write_file.cc +++ b/passes/cmds/write_file.cc @@ -70,7 +70,7 @@ struct WriteFileFrontend : public Frontend { char buffer[64 * 1024]; size_t bytes; - while (0 < (bytes = f->readsome(buffer, sizeof(buffer)))) + while (0 < (bytes = readsome(*f, buffer, sizeof(buffer)))) fwrite(buffer, bytes, 1, of); fclose(of); From 35fbc0b35fb2dafa1b7d1df98ed72688e2eeead6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 Oct 2014 11:42:08 +0200 Subject: [PATCH 036/492] Do not the 'z' modifier in format string (another win32 fix) --- frontends/ast/ast.cc | 4 ++-- passes/fsm/fsm_expand.cc | 2 +- passes/fsm/fsm_recode.cc | 6 +++--- passes/hierarchy/hierarchy.cc | 2 +- passes/opt/opt_muxtree.cc | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 1e43875ae..87b073ff3 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -267,7 +267,7 @@ void AstNode::dumpAst(FILE *f, std::string indent) bits[i-1] == RTLIL::S1 ? '1' : bits[i-1] == RTLIL::Sx ? 'x' : bits[i-1] == RTLIL::Sz ? 'z' : '?'); - fprintf(f, "'(%zd)", bits.size()); + fprintf(f, "'(%d)", GetSize(bits)); } if (is_input) fprintf(f, " input"); @@ -471,7 +471,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) else if (bits.size() == 32) fprintf(f, "%d", RTLIL::Const(bits).as_int()); else - fprintf(f, "%zd'b %s", bits.size(), RTLIL::Const(bits).as_string().c_str()); + fprintf(f, "%d'b %s", GetSize(bits), RTLIL::Const(bits).as_string().c_str()); break; case AST_REALVALUE: diff --git a/passes/fsm/fsm_expand.cc b/passes/fsm/fsm_expand.cc index ecd4bf762..a261eb22b 100644 --- a/passes/fsm/fsm_expand.cc +++ b/passes/fsm/fsm_expand.cc @@ -239,7 +239,7 @@ struct FsmExpand if (merged_set.size() > 0 && !already_optimized) FsmData::optimize_fsm(fsm_cell, module); - log(" merged %zd cells into FSM.\n", merged_set.size()); + log(" merged %d cells into FSM.\n", GetSize(merged_set)); } }; diff --git a/passes/fsm/fsm_recode.cc b/passes/fsm/fsm_recode.cc index 2b9a26d44..06ac58f0f 100644 --- a/passes/fsm/fsm_recode.cc +++ b/passes/fsm/fsm_recode.cc @@ -41,9 +41,9 @@ static void fm_set_fsm_print(RTLIL::Cell *cell, RTLIL::Module *module, FsmData & prefix, RTLIL::unescape_id(module->name).c_str()); fprintf(f, "set_fsm_encoding {"); - for (size_t i = 0; i < fsm_data.state_table.size(); i++) { - fprintf(f, " s%zd=2#", i); - for (int j = int(fsm_data.state_table[i].bits.size())-1; j >= 0; j--) + for (int i = 0; i < GetSize(fsm_data.state_table); i++) { + fprintf(f, " s%d=2#", i); + for (int j = GetSize(fsm_data.state_table[i].bits)-1; j >= 0; j--) fprintf(f, "%c", fsm_data.state_table[i].bits[j] == RTLIL::State::S1 ? '1' : '0'); } fprintf(f, " } -name {%s_%s} {%s:/WORK/%s}\n", diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 87d115027..4b414d3cb 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -281,7 +281,7 @@ void hierarchy(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib, bool f delete mod; } - log("Removed %zd unused modules.\n", del_modules.size()); + log("Removed %d unused modules.\n", GetSize(del_modules)); } bool set_keep_assert(std::map &cache, RTLIL::Module *mod) diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 88ae43f0e..7bdc54afa 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -174,12 +174,12 @@ struct OptMuxtreeWorker for (auto &mi : mux2info) { std::vector live_ports; - for (size_t port_idx = 0; port_idx < mi.ports.size(); port_idx++) { + for (int port_idx = 0; port_idx < GetSize(mi.ports); port_idx++) { portinfo_t &pi = mi.ports[port_idx]; if (pi.enabled) { live_ports.push_back(port_idx); } else { - log(" dead port %zd/%zd on %s %s.\n", port_idx+1, mi.ports.size(), + log(" dead port %d/%d on %s %s.\n", port_idx+1, GetSize(mi.ports), mi.cell->type.c_str(), mi.cell->name.c_str()); removed_count++; } From 217c7c7b8d1f46ed0b4d8b8a4fbe1b10c0157a6a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 Oct 2014 11:44:36 +0200 Subject: [PATCH 037/492] Fixed Makefile PRETTY=1 for MXE (win32) and EMCC (js) builds --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 8a4ff52e8..46ac373fb 100644 --- a/Makefile +++ b/Makefile @@ -139,8 +139,8 @@ endif ifeq ($(PRETTY), 1) P_STATUS = 0 P_OFFSET = 0 -P_UPDATE = $(eval P_STATUS=$(shell echo $(OBJS) yosys | gawk 'BEGIN { RS = " "; I = $(P_STATUS)+0; } $$1 == "$@" && NR > I { I = NR; } END { print I; }')) -P_SHOW = [$(shell gawk "BEGIN { N=$(words $(OBJS) yosys); printf \"%3d\", $(P_OFFSET)+90*$(P_STATUS)/N; exit; }")%] +P_UPDATE = $(eval P_STATUS=$(shell echo $(OBJS) yosys$(EXE) | gawk 'BEGIN { RS = " "; I = $(P_STATUS)+0; } $$1 == "$@" && NR > I { I = NR; } END { print I; }')) +P_SHOW = [$(shell gawk "BEGIN { N=$(words $(OBJS) yosys$(EXE)); printf \"%3d\", $(P_OFFSET)+90*$(P_STATUS)/N; exit; }")%] P = @echo "$(if $(findstring $@,$(TARGETS) $(EXTRA_TARGETS)),$(eval P_OFFSET = 10))$(call P_UPDATE)$(call P_SHOW) Building $@"; Q = @ S = -s From f30aee01f9db3f44cd05e1429a914a79192dd1b5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 Oct 2014 11:53:36 +0200 Subject: [PATCH 038/492] Added "make dist" for mxe builds --- Makefile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Makefile b/Makefile index 46ac373fb..0eb5de2bc 100644 --- a/Makefile +++ b/Makefile @@ -309,6 +309,16 @@ qtcreator: { echo .; find backends frontends kernel libs passes -type f \( -name '*.h' -o -name '*.hh' \) -printf '%h\n' | sort -u; } > qtcreator.includes touch qtcreator.config qtcreator.creator +ifeq ($(CONFIG),mxe) +dist: $(TARGETS) $(EXTRA_TARGETS) + rm -rf yosys-win32-$(YOSYS_VER) + mkdir -p yosys-win32-$(YOSYS_VER) + cp -r yosys.exe share/ yosys-win32-$(YOSYS_VER)/ + echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-$(YOSYS_VER)/readme.txt + echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-$(YOSYS_VER)/readme.txt + zip -r yosys-win32-$(YOSYS_VER).zip yosys-win32-$(YOSYS_VER)/ +endif + config-clean: clean rm -f Makefile.conf From 0dc249ccd78fa7e3366a89cf46f209ff5ce09e26 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 Oct 2014 11:59:35 +0200 Subject: [PATCH 039/492] Shrinked the copyright banner by 1 character --- kernel/driver.cc | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index 8a0939043..8117a61c5 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -203,25 +203,25 @@ int main(int argc, char **argv) if (print_banner) { log("\n"); - log(" /-----------------------------------------------------------------------------\\\n"); - log(" | |\n"); - log(" | yosys -- Yosys Open SYnthesis Suite |\n"); - log(" | |\n"); - log(" | Copyright (C) 2012 Clifford Wolf |\n"); - log(" | |\n"); - log(" | Permission to use, copy, modify, and/or distribute this software for any |\n"); - log(" | purpose with or without fee is hereby granted, provided that the above |\n"); - log(" | copyright notice and this permission notice appear in all copies. |\n"); - log(" | |\n"); - log(" | THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |\n"); - log(" | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |\n"); - log(" | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |\n"); - log(" | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |\n"); - log(" | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |\n"); - log(" | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |\n"); - log(" | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |\n"); - log(" | |\n"); - log(" \\-----------------------------------------------------------------------------/\n"); + log(" /----------------------------------------------------------------------------\\\n"); + log(" | |\n"); + log(" | yosys -- Yosys Open SYnthesis Suite |\n"); + log(" | |\n"); + log(" | Copyright (C) 2012 Clifford Wolf |\n"); + log(" | |\n"); + log(" | Permission to use, copy, modify, and/or distribute this software for any |\n"); + log(" | purpose with or without fee is hereby granted, provided that the above |\n"); + log(" | copyright notice and this permission notice appear in all copies. |\n"); + log(" | |\n"); + log(" | THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |\n"); + log(" | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |\n"); + log(" | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |\n"); + log(" | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |\n"); + log(" | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |\n"); + log(" | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |\n"); + log(" | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |\n"); + log(" | |\n"); + log(" \\----------------------------------------------------------------------------/\n"); log("\n"); log(" %s\n", yosys_version_str); log("\n"); From d2b8b48bf3bc6b202c31db62ef5e2b63041e775e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 11 Oct 2014 12:13:46 +0200 Subject: [PATCH 040/492] Renamed "log.cc" to "logcmd.cc" so there aren't two "log.cc" in the source tree --- passes/cmds/Makefile.inc | 2 +- passes/cmds/{log.cc => logcmd.cc} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename passes/cmds/{log.cc => logcmd.cc} (100%) diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc index eba61d1df..0e62abbc4 100644 --- a/passes/cmds/Makefile.inc +++ b/passes/cmds/Makefile.inc @@ -14,7 +14,7 @@ OBJS += passes/cmds/setattr.o OBJS += passes/cmds/copy.o OBJS += passes/cmds/splice.o OBJS += passes/cmds/scc.o -OBJS += passes/cmds/log.o +OBJS += passes/cmds/logcmd.o OBJS += passes/cmds/tee.o OBJS += passes/cmds/write_file.o OBJS += passes/cmds/connwrappers.o diff --git a/passes/cmds/log.cc b/passes/cmds/logcmd.cc similarity index 100% rename from passes/cmds/log.cc rename to passes/cmds/logcmd.cc From b1596bc0e7e5269fd610508f608f65f3aa696bd9 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 12 Oct 2014 10:57:15 +0200 Subject: [PATCH 041/492] Added run_command() api to replace system() and popen() --- frontends/vhdl2verilog/vhdl2verilog.cc | 19 +--- kernel/register.cc | 2 +- kernel/yosys.cc | 25 +++++ kernel/yosys.h | 1 + passes/abc/abc.cc | 143 ++++++++++++------------- passes/cmds/show.cc | 6 +- 6 files changed, 104 insertions(+), 92 deletions(-) diff --git a/frontends/vhdl2verilog/vhdl2verilog.cc b/frontends/vhdl2verilog/vhdl2verilog.cc index a8c411c7b..3895ecfd2 100644 --- a/frontends/vhdl2verilog/vhdl2verilog.cc +++ b/frontends/vhdl2verilog/vhdl2verilog.cc @@ -165,20 +165,9 @@ struct Vhdl2verilogPass : public Pass { log("Running '%s'..\n", command.c_str()); - errno = ENOMEM; // popen does not set errno if memory allocation fails, therefore set it by hand - f = popen(command.c_str(), "r"); - if (f == NULL) - log_error("Opening pipe to `%s' for reading failed: %s\n", command.c_str(), strerror(errno)); - - char logbuf[1024]; - while (fgets(logbuf, 1024, f) != NULL) - log("%s", logbuf); - - int ret = pclose(f); - if (ret < 0) - log_error("Closing pipe to `%s' failed: %s\n", command.c_str(), strerror(errno)); - if (WEXITSTATUS(ret) != 0) - log_error("Execution of command \"%s\" failed: the shell returned %d\n", command.c_str(), WEXITSTATUS(ret)); + int ret = run_command(command, [](const std::string &line) { log("%s", line.c_str()); }); + if (ret != 0) + log_error("Execution of command \"%s\" failed: return code %d.\n", command.c_str(), ret); if (out_file.empty()) { std::ifstream ff; @@ -189,7 +178,7 @@ struct Vhdl2verilogPass : public Pass { } log_header("Removing temp directory `%s':\n", tempdir_name); - if (system(stringf("rm -rf '%s'", tempdir_name).c_str()) != 0) + if (run_command(stringf("rm -rf '%s'", tempdir_name).c_str()) != 0) log_error("Execution of \"rm -rf '%s'\" failed!\n", tempdir_name); log_pop(); diff --git a/kernel/register.cc b/kernel/register.cc index 9452eb355..33c129d83 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -159,7 +159,7 @@ void Pass::call(RTLIL::Design *design, std::string command) cmd_buf.back() == '\r' || cmd_buf.back() == '\n')) cmd_buf.resize(cmd_buf.size()-1); log_header("Shell command: %s\n", cmd_buf.c_str()); - int retCode = system(cmd_buf.c_str()); + int retCode = run_command(cmd_buf); if (retCode != 0) log_cmd_error("Shell command returned error code %d.\n", retCode); return; diff --git a/kernel/yosys.cc b/kernel/yosys.cc index a40ad4372..50da13ae7 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -182,6 +182,31 @@ int readsome(std::istream &f, char *s, int n) return rc; } +int run_command(const std::string &command, std::function process_line) +{ + if (!process_line) + return system(command.c_str()); + + FILE *f = popen(command.c_str(), "r"); + if (f == nullptr) + return -1; + + std::string line; + char logbuf[128]; + while (fgets(logbuf, 128, f) != NULL) { + line += logbuf; + if (!line.empty() && line.back() == '\n') + process_line(line), line.clear(); + } + if (!line.empty()) + process_line(line); + + int ret = pclose(f); + if (ret < 0) + return -1; + return WEXITSTATUS(ret); +} + int GetSize(RTLIL::Wire *wire) { return wire->width; diff --git a/kernel/yosys.h b/kernel/yosys.h index d38e60ceb..fcf60f9f1 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -87,6 +87,7 @@ std::string vstringf(const char *fmt, va_list ap); std::string next_token(std::string &text, const char *sep); bool patmatch(const char *pattern, const char *string); int readsome(std::istream &f, char *s, int n); +int run_command(const std::string &command, std::function process_line = std::function()); template int GetSize(const T &obj) { return obj.size(); } int GetSize(RTLIL::Wire *wire); diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 487894941..bc7ccc065 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -86,16 +86,16 @@ struct gate_t RTLIL::SigBit bit; }; -static int map_autoidx; -static SigMap assign_map; -static RTLIL::Module *module; -static std::vector signal_list; -static std::map signal_map; +int map_autoidx; +SigMap assign_map; +RTLIL::Module *module; +std::vector signal_list; +std::map signal_map; -static bool clk_polarity; -static RTLIL::SigSpec clk_sig; +bool clk_polarity; +RTLIL::SigSpec clk_sig; -static int map_signal(RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1, int in2 = -1, int in3 = -1, int in4 = -1) +int map_signal(RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1, int in2 = -1, int in3 = -1, int in4 = -1) { assign_map.apply(bit); @@ -129,14 +129,14 @@ static int map_signal(RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in return gate.id; } -static void mark_port(RTLIL::SigSpec sig) +void mark_port(RTLIL::SigSpec sig) { for (auto &bit : assign_map(sig)) if (bit.wire != NULL && signal_map.count(bit) > 0) signal_list[signal_map[bit]].is_port = true; } -static void extract_cell(RTLIL::Cell *cell, bool keepff) +void extract_cell(RTLIL::Cell *cell, bool keepff) { if (cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_") { @@ -278,14 +278,14 @@ static void extract_cell(RTLIL::Cell *cell, bool keepff) } } -static std::string remap_name(RTLIL::IdString abc_name) +std::string remap_name(RTLIL::IdString abc_name) { std::stringstream sstr; sstr << "$abc$" << map_autoidx << "$" << abc_name.substr(1); return sstr.str(); } -static void dump_loop_graph(FILE *f, int &nr, std::map> &edges, std::set &workpool, std::vector &in_counts) +void dump_loop_graph(FILE *f, int &nr, std::map> &edges, std::set &workpool, std::vector &in_counts) { if (f == NULL) return; @@ -314,7 +314,7 @@ static void dump_loop_graph(FILE *f, int &nr, std::map> &edge fprintf(f, "}\n"); } -static void handle_loops() +void handle_loops() { // http://en.wikipedia.org/wiki/Topological_sorting // (Kahn, Arthur B. (1962), "Topological sorting of large networks") @@ -447,7 +447,7 @@ static void handle_loops() fclose(dot_f); } -static std::string add_echos_to_abc_cmd(std::string str) +std::string add_echos_to_abc_cmd(std::string str) { std::string new_str, token; for (size_t i = 0; i < str.size(); i++) { @@ -471,7 +471,7 @@ static std::string add_echos_to_abc_cmd(std::string str) return new_str; } -static std::string fold_abc_cmd(std::string str) +std::string fold_abc_cmd(std::string str) { std::string token, new_str = " "; int char_counter = 10; @@ -490,7 +490,56 @@ static std::string fold_abc_cmd(std::string str) return new_str; } -static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, +struct abc_output_filter +{ + bool got_cr; + int escape_seq_state; + std::string linebuf; + + abc_output_filter() + { + got_cr = false; + escape_seq_state = 0; + } + + void next_char(char ch) + { + if (escape_seq_state == 0 && ch == '\033') { + escape_seq_state = 1; + return; + } + if (escape_seq_state == 1) { + escape_seq_state = ch == '[' ? 2 : 0; + return; + } + if (escape_seq_state == 2) { + if ((ch < '0' || '9' < ch) && ch != ';') + escape_seq_state = 0; + return; + } + escape_seq_state = 0; + if (ch == '\r') { + got_cr = true; + return; + } + if (ch == '\n') { + log("ABC: %s\n", linebuf.c_str()); + got_cr = false, linebuf.clear(); + return; + } + if (got_cr) + got_cr = false, linebuf.clear(); + linebuf += ch; + } + + void next_line(const std::string &line) + { + for (char ch : line) + next_char(ch); + } +}; + +void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, std::string liberty_file, std::string constr_file, bool cleanup, int lut_mode, bool dff_mode, std::string clk_str, bool keepff, std::string delay_target, bool fast_mode) { @@ -767,62 +816,10 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std log("%s\n", buffer.c_str()); - errno = ENOMEM; // popen does not set errno if memory allocation fails, therefore set it by hand - f = popen(buffer.c_str(), "r"); - if (f == NULL) - log_error("Opening pipe to `%s' for reading failed: %s\n", buffer.c_str(), strerror(errno)); -#if 0 - char logbuf[1024]; - while (fgets(logbuf, 1024, f) != NULL) - log("ABC: %s", logbuf); -#else - bool got_cr = false; - int escape_seq_state = 0; - std::string linebuf; - char logbuf[1024]; - while (fgets(logbuf, 1024, f) != NULL) - for (char *p = logbuf; *p; p++) { - if (escape_seq_state == 0 && *p == '\033') { - escape_seq_state = 1; - continue; - } - if (escape_seq_state == 1) { - escape_seq_state = *p == '[' ? 2 : 0; - continue; - } - if (escape_seq_state == 2) { - if ((*p < '0' || '9' < *p) && *p != ';') - escape_seq_state = 0; - continue; - } - escape_seq_state = 0; - if (*p == '\r') { - got_cr = true; - continue; - } - if (*p == '\n') { - log("ABC: %s\n", linebuf.c_str()); - got_cr = false, linebuf.clear(); - continue; - } - if (got_cr) - got_cr = false, linebuf.clear(); - linebuf += *p; - } - if (!linebuf.empty()) - log("ABC: %s\n", linebuf.c_str()); -#endif - errno = 0; - int ret = pclose(f); - if (ret < 0) - log_error("Closing pipe to `%s' failed: %s\n", buffer.c_str(), strerror(errno)); - if (WEXITSTATUS(ret) != 0) { - switch (WEXITSTATUS(ret)) { - case 127: log_error("ABC: execution of command \"%s\" failed: Command not found\n", exe_file.c_str()); break; - case 126: log_error("ABC: execution of command \"%s\" failed: Command not executable\n", exe_file.c_str()); break; - default: log_error("ABC: execution of command \"%s\" failed: the shell returned %d\n", exe_file.c_str(), WEXITSTATUS(ret)); break; - } - } + abc_output_filter filt; + int ret = run_command(buffer, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1)); + if (ret != 0) + log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); if (asprintf(&p, "%s/%s", tempdir_name, "output.blif") < 0) log_abort(); f = fopen(p, "rt"); @@ -1215,4 +1212,4 @@ struct AbcPass : public Pass { } } AbcPass; - PRIVATE_NAMESPACE_END +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index 1599879a1..c6335cb30 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -760,20 +760,20 @@ struct ShowPass : public Pass { if (format != "dot" && !format.empty()) { std::string cmd = stringf("dot -T%s -o '%s' '%s'", format.c_str(), out_file.c_str(), dot_file.c_str()); log("Exec: %s\n", cmd.c_str()); - if (system(cmd.c_str()) != 0) + if (run_command(cmd) != 0) log_cmd_error("Shell command failed!\n"); } if (!viewer_exe.empty()) { std::string cmd = stringf("%s '%s' &", viewer_exe.c_str(), out_file.c_str()); log("Exec: %s\n", cmd.c_str()); - if (system(cmd.c_str()) != 0) + if (run_command(cmd) != 0) log_cmd_error("Shell command failed!\n"); } else if (format.empty()) { std::string cmd = stringf("fuser -s '%s' || xdot '%s' < '%s' &", dot_file.c_str(), dot_file.c_str(), dot_file.c_str()); log("Exec: %s\n", cmd.c_str()); - if (system(cmd.c_str()) != 0) + if (run_command(cmd) != 0) log_cmd_error("Shell command failed!\n"); } From 9b4d171e37aa23adbdbad1ca1e983e4bf35604f9 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 12 Oct 2014 11:17:53 +0200 Subject: [PATCH 042/492] Using stringf() instead of asprintf() in "abc" pass --- passes/abc/abc.cc | 53 +++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index bc7ccc065..82ebead71 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -653,11 +653,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin handle_loops(); - if (asprintf(&p, "%s/input.blif", tempdir_name) < 0) log_abort(); - FILE *f = fopen(p, "wt"); + std::string buffer = stringf("%s/input.blif", tempdir_name); + FILE *f = fopen(buffer.c_str(), "wt"); if (f == NULL) - log_error("Opening %s for writing failed: %s\n", p, strerror(errno)); - free(p); + log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); fprintf(f, ".model netlist\n"); @@ -757,18 +756,18 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin fprintf(f, ".end\n"); fclose(f); - log("Extracted %d gates and %zd wires to a netlist network with %d inputs and %d outputs.\n", - count_gates, signal_list.size(), count_input, count_output); + log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n", + count_gates, GetSize(signal_list), count_input, count_output); log_push(); if (count_output > 0) { log_header("Executing ABC.\n"); - if (asprintf(&p, "%s/stdcells.genlib", tempdir_name) < 0) log_abort(); - f = fopen(p, "wt"); + buffer = stringf("%s/stdcells.genlib", tempdir_name); + f = fopen(buffer.c_str(), "wt"); if (f == NULL) - log_error("Opening %s for writing failed: %s\n", p, strerror(errno)); + log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); fprintf(f, "GATE ZERO 1 Y=CONST0;\n"); fprintf(f, "GATE ONE 1 Y=CONST1;\n"); fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_BUF_")); @@ -785,33 +784,31 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI4_")); fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_MUX_")); fclose(f); - free(p); if (lut_mode) { - if (asprintf(&p, "%s/lutdefs.txt", tempdir_name) < 0) log_abort(); - f = fopen(p, "wt"); + buffer = stringf("%s/lutdefs.txt", tempdir_name); + f = fopen(buffer.c_str(), "wt"); if (f == NULL) - log_error("Opening %s for writing failed: %s\n", p, strerror(errno)); + log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); for (int i = 0; i < lut_mode; i++) fprintf(f, "%d 1.00 1.00\n", i+1); fclose(f); - free(p); } - std::string buffer; + buffer = stringf("%s -s -c '", exe_file.c_str()); if (!liberty_file.empty()) { - buffer += stringf("%s -s -c 'read_blif %s/input.blif; read_lib -w %s; ", - exe_file.c_str(), tempdir_name, liberty_file.c_str()); + buffer += stringf("read_blif %s/input.blif; read_lib -w %s; ", + tempdir_name, liberty_file.c_str()); if (!constr_file.empty()) buffer += stringf("read_constr -v %s; ", constr_file.c_str()); buffer += abc_command + "; "; } else if (lut_mode) - buffer += stringf("%s -s -c 'read_blif %s/input.blif; read_lut %s/lutdefs.txt; %s; ", - exe_file.c_str(), tempdir_name, tempdir_name, abc_command.c_str()); + buffer += stringf("read_blif %s/input.blif; read_lut %s/lutdefs.txt; %s; ", + tempdir_name, tempdir_name, abc_command.c_str()); else - buffer += stringf("%s -s -c 'read_blif %s/input.blif; read_library %s/stdcells.genlib; %s; ", - exe_file.c_str(), tempdir_name, tempdir_name, abc_command.c_str()); + buffer += stringf("read_blif %s/input.blif; read_library %s/stdcells.genlib; %s; ", + tempdir_name, tempdir_name, abc_command.c_str()); buffer += stringf("write_blif %s/output.blif' 2>&1", tempdir_name); log("%s\n", buffer.c_str()); @@ -821,16 +818,15 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (ret != 0) log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); - if (asprintf(&p, "%s/%s", tempdir_name, "output.blif") < 0) log_abort(); - f = fopen(p, "rt"); + buffer = stringf("%s/%s", tempdir_name, "output.blif"); + f = fopen(buffer.c_str(), "rt"); if (f == NULL) - log_error("Can't open ABC output file `%s'.\n", p); + log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); bool builtin_lib = liberty_file.empty() && script_file.empty() && !lut_mode; RTLIL::Design *mapped_design = abc_parse_blif(f, builtin_lib ? "\\DFF" : "\\_dff_"); fclose(f); - free(p); log_header("Re-integrating ABC results.\n"); RTLIL::Module *mapped_mod = mapped_design->modules_["\\netlist"]; @@ -1002,10 +998,9 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin log_assert(n >= 0); for (int i = 0; i < n; i++) { if (strcmp(namelist[i]->d_name, ".") && strcmp(namelist[i]->d_name, "..")) { - if (asprintf(&p, "%s/%s", tempdir_name, namelist[i]->d_name) < 0) log_abort(); - log("Removing `%s'.\n", p); - remove(p); - free(p); + buffer = stringf("%s/%s", tempdir_name, namelist[i]->d_name); + log("Removing `%s'.\n", buffer.c_str()); + remove(buffer.c_str()); } free(namelist[i]); } From 0b9282a779867459fe5babfff300795c343c46ea Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 12 Oct 2014 12:11:57 +0200 Subject: [PATCH 043/492] Added make_temp_{file,dir}() and remove_directory() APIs --- frontends/vhdl2verilog/vhdl2verilog.cc | 26 +++----- kernel/yosys.cc | 90 ++++++++++++++++++++++++++ kernel/yosys.h | 3 + passes/abc/abc.cc | 46 +++++-------- 4 files changed, 116 insertions(+), 49 deletions(-) diff --git a/frontends/vhdl2verilog/vhdl2verilog.cc b/frontends/vhdl2verilog/vhdl2verilog.cc index 3895ecfd2..39b4f1496 100644 --- a/frontends/vhdl2verilog/vhdl2verilog.cc +++ b/frontends/vhdl2verilog/vhdl2verilog.cc @@ -120,15 +120,8 @@ struct Vhdl2verilogPass : public Pass { if (top_entity.empty()) log_cmd_error("Missing -top option.\n"); -#ifdef _WIN32 - #warning Fixme: The vhdl2veriog command has not been ported to win32. - log_cmd_error("The vhdl2veriog command has not been ported to win32.\n"); -#else - char tempdir_name[] = "/tmp/yosys-vhdl2verilog-XXXXXX"; - char *p = mkdtemp(tempdir_name); - log("Using temp directory %s.\n", tempdir_name); - if (p == NULL) - log_error("For some reason mkdtemp() failed!\n"); + std::string tempdir_name = make_temp_dir("/tmp/yosys-vhdl2verilog-XXXXXX"); + log("Using temp directory %s.\n", tempdir_name.c_str()); if (!out_file.empty() && out_file[0] != '/') { char pwd[PATH_MAX]; @@ -139,7 +132,7 @@ struct Vhdl2verilogPass : public Pass { out_file = pwd + ("/" + out_file); } - FILE *f = fopen(stringf("%s/files.list", tempdir_name).c_str(), "wt"); + FILE *f = fopen(stringf("%s/files.list", tempdir_name.c_str()).c_str(), "wt"); while (argidx < args.size()) { std::string file = args[argidx++]; if (file.empty()) @@ -160,7 +153,7 @@ struct Vhdl2verilogPass : public Pass { std::string command = "exec 2>&1; "; if (!vhdl2verilog_dir.empty()) command += stringf("cd '%s'; . ./setup_env.sh; ", vhdl2verilog_dir.c_str()); - command += stringf("cd '%s'; vhdl2verilog -out '%s' -filelist files.list -top '%s'%s", tempdir_name, + command += stringf("cd '%s'; vhdl2verilog -out '%s' -filelist files.list -top '%s'%s", tempdir_name.c_str(), out_file.empty() ? "vhdl2verilog_output.v" : out_file.c_str(), top_entity.c_str(), extra_opts.c_str()); log("Running '%s'..\n", command.c_str()); @@ -171,18 +164,15 @@ struct Vhdl2verilogPass : public Pass { if (out_file.empty()) { std::ifstream ff; - ff.open(stringf("%s/vhdl2verilog_output.v", tempdir_name).c_str()); + ff.open(stringf("%s/vhdl2verilog_output.v", tempdir_name.c_str()).c_str()); if (ff.fail()) log_error("Can't open vhdl2verilog output file `vhdl2verilog_output.v'.\n"); - Frontend::frontend_call(design, &ff, stringf("%s/vhdl2verilog_output.v", tempdir_name), "verilog"); + Frontend::frontend_call(design, &ff, stringf("%s/vhdl2verilog_output.v", tempdir_name.c_str()), "verilog"); } - log_header("Removing temp directory `%s':\n", tempdir_name); - if (run_command(stringf("rm -rf '%s'", tempdir_name).c_str()) != 0) - log_error("Execution of \"rm -rf '%s'\" failed!\n", tempdir_name); - + log_header("Removing temp directory `%s':\n", tempdir_name.c_str()); + remove_directory(tempdir_name); log_pop(); -#endif } } Vhdl2verilogPass; diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 50da13ae7..4af3ff9c0 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -34,6 +34,7 @@ #include #include +#include #include YOSYS_NAMESPACE_BEGIN @@ -204,7 +205,96 @@ int run_command(const std::string &command, std::function> 17, x ^= x << 5; + template_str[pos+i] = y[x % y.size()]; + } + if (access(template_str.c_str(), F_OK) != 0) + break; + } +#else + size_t pos = template_str.rfind("XXXXXX"); + log_assert(pos != std::string::npos); + + int suffixlen = GetSize(template_str) - pos - 6; + + char *p = strdup(template_str.c_str()); + close(mkstemps(p, suffixlen)); + template_str = p; + free(p); +#endif + + return template_str; +} + +std::string make_temp_dir(std::string template_str) +{ +#ifdef _WIN32 + template_str = make_temp_file(template_str); + mkdir(template_str.c_str()); + return template_str; +#else + size_t pos = template_str.rfind("XXXXXX"); + log_assert(pos != std::string::npos); + + int suffixlen = GetSize(template_str) - pos - 6; + log_assert(suffixlen == 0); + + char *p = strdup(template_str.c_str()); + mkdtemp(p, suffixlen); + template_str = p; + free(p); + + return template_str; +#endif +} + +void remove_directory(std::string dirname) +{ +#ifdef _WIN32 + run_command(stringf("rmdir /s /q \"%s\"", dirname.c_str())); +#else + struct stat stbuf; + struct dirent **namelist; + int n = scandir(dirname.c_str(), &namelist, nullptr, alphasort); + log_assert(n >= 0); + for (int i = 0; i < n; i++) { + if (strcmp(namelist[i]->d_name, ".") && strcmp(namelist[i]->d_name, "..")) { + buffer = stringf("%s/%s", dirname.c_str(), namelist[i]->d_name); + if (!stat(buffer.c_str(), &stbuf) && S_ISREG(stbuf.st_mode)) { + log("Removing `%s'.\n", buffer.c_str()); + remove(buffer.c_str()); + } else + remove_directory(buffer); + } + free(namelist[i]); + } + free(namelist); + log("Removing `%s'.\n", dirname.c_str()); + rmdir(dirname.c_str()); +#endif } int GetSize(RTLIL::Wire *wire) diff --git a/kernel/yosys.h b/kernel/yosys.h index fcf60f9f1..e579e90d9 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -88,6 +88,9 @@ std::string next_token(std::string &text, const char *sep); bool patmatch(const char *pattern, const char *string); int readsome(std::istream &f, char *s, int n); int run_command(const std::string &command, std::function process_line = std::function()); +std::string make_temp_file(std::string template_str = "/tmp/yosys_XXXXXX"); +std::string make_temp_dir(std::string template_str = "/tmp/yosys_XXXXXX"); +void remove_directory(std::string dirname); template int GetSize(const T &obj) { return obj.size(); } int GetSize(RTLIL::Wire *wire); diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 82ebead71..c63867068 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -553,13 +553,11 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin clk_polarity = true; clk_sig = RTLIL::SigSpec(); - char tempdir_name[] = "/tmp/yosys-abc-XXXXXX"; + std::string tempdir_name = "/tmp/yosys-abc-XXXXXX"; if (!cleanup) tempdir_name[0] = tempdir_name[4] = '_'; - char *p = mkdtemp(tempdir_name); - log_header("Extracting gate netlist of module `%s' to `%s/input.blif'..\n", module->name.c_str(), tempdir_name); - if (p == NULL) - log_error("For some reason mkdtemp() failed!\n"); + tempdir_name = make_temp_dir(tempdir_name); + log_header("Extracting gate netlist of module `%s' to `%s/input.blif'..\n", module->name.c_str(), tempdir_name.c_str()); std::string abc_command; if (!script_file.empty()) { @@ -589,10 +587,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin for (size_t i = 0; i+1 < abc_command.size(); i++) if (abc_command[i] == ';' && abc_command[i+1] == ' ') abc_command[i+1] = '\n'; - FILE *f = fopen(stringf("%s/abc.script", tempdir_name).c_str(), "wt"); + FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt"); fprintf(f, "%s\n", abc_command.c_str()); fclose(f); - abc_command = stringf("source %s/abc.script", tempdir_name); + abc_command = stringf("source %s/abc.script", tempdir_name.c_str()); } if (clk_str.empty()) { @@ -653,7 +651,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin handle_loops(); - std::string buffer = stringf("%s/input.blif", tempdir_name); + std::string buffer = stringf("%s/input.blif", tempdir_name.c_str()); FILE *f = fopen(buffer.c_str(), "wt"); if (f == NULL) log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); @@ -764,7 +762,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin { log_header("Executing ABC.\n"); - buffer = stringf("%s/stdcells.genlib", tempdir_name); + buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str()); f = fopen(buffer.c_str(), "wt"); if (f == NULL) log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); @@ -786,7 +784,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin fclose(f); if (lut_mode) { - buffer = stringf("%s/lutdefs.txt", tempdir_name); + buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str()); f = fopen(buffer.c_str(), "wt"); if (f == NULL) log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); @@ -798,18 +796,18 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin buffer = stringf("%s -s -c '", exe_file.c_str()); if (!liberty_file.empty()) { buffer += stringf("read_blif %s/input.blif; read_lib -w %s; ", - tempdir_name, liberty_file.c_str()); + tempdir_name.c_str(), liberty_file.c_str()); if (!constr_file.empty()) buffer += stringf("read_constr -v %s; ", constr_file.c_str()); buffer += abc_command + "; "; } else if (lut_mode) buffer += stringf("read_blif %s/input.blif; read_lut %s/lutdefs.txt; %s; ", - tempdir_name, tempdir_name, abc_command.c_str()); + tempdir_name.c_str(), tempdir_name.c_str(), abc_command.c_str()); else buffer += stringf("read_blif %s/input.blif; read_library %s/stdcells.genlib; %s; ", - tempdir_name, tempdir_name, abc_command.c_str()); - buffer += stringf("write_blif %s/output.blif' 2>&1", tempdir_name); + tempdir_name.c_str(), tempdir_name.c_str(), abc_command.c_str()); + buffer += stringf("write_blif %s/output.blif' 2>&1", tempdir_name.c_str()); log("%s\n", buffer.c_str()); @@ -818,7 +816,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (ret != 0) log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); - buffer = stringf("%s/%s", tempdir_name, "output.blif"); + buffer = stringf("%s/%s", tempdir_name.c_str(), "output.blif"); f = fopen(buffer.c_str(), "rt"); if (f == NULL) log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); @@ -991,22 +989,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (cleanup) { - log_header("Removing temp directory `%s':\n", tempdir_name); - - struct dirent **namelist; - int n = scandir(tempdir_name, &namelist, 0, alphasort); - log_assert(n >= 0); - for (int i = 0; i < n; i++) { - if (strcmp(namelist[i]->d_name, ".") && strcmp(namelist[i]->d_name, "..")) { - buffer = stringf("%s/%s", tempdir_name, namelist[i]->d_name); - log("Removing `%s'.\n", buffer.c_str()); - remove(buffer.c_str()); - } - free(namelist[i]); - } - free(namelist); - log("Removing `%s'.\n", tempdir_name); - rmdir(tempdir_name); + log_header("Removing temp directory `%s':\n", tempdir_name.c_str()); + remove_directory(tempdir_name); } log_pop(); From 1a7684be24ba5d776c4f1f4c0889e1200c41d7b6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 12 Oct 2014 12:18:38 +0200 Subject: [PATCH 044/492] Various small fixes for non-win32 builds --- kernel/yosys.cc | 10 +++++++--- kernel/yosys.h | 5 ++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 4af3ff9c0..fa14c5d9a 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -30,6 +30,11 @@ #ifdef _WIN32 # include +#elif defined(__APPLE__) +# include +#else +# include +# include #endif #include @@ -263,7 +268,7 @@ std::string make_temp_dir(std::string template_str) log_assert(suffixlen == 0); char *p = strdup(template_str.c_str()); - mkdtemp(p, suffixlen); + mkdtemp(p); template_str = p; free(p); @@ -282,7 +287,7 @@ void remove_directory(std::string dirname) log_assert(n >= 0); for (int i = 0; i < n; i++) { if (strcmp(namelist[i]->d_name, ".") && strcmp(namelist[i]->d_name, "..")) { - buffer = stringf("%s/%s", dirname.c_str(), namelist[i]->d_name); + std::string buffer = stringf("%s/%s", dirname.c_str(), namelist[i]->d_name); if (!stat(buffer.c_str(), &stbuf) && S_ISREG(stbuf.st_mode)) { log("Removing `%s'.\n", buffer.c_str()); remove(buffer.c_str()); @@ -455,7 +460,6 @@ std::string proc_self_dirname() return std::string(path, buflen); } #elif defined(__APPLE__) -#include std::string proc_self_dirname() { char *path = NULL; diff --git a/kernel/yosys.h b/kernel/yosys.h index e579e90d9..5a37dd3c5 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -58,6 +58,10 @@ #include #include +#ifdef YOSYS_ENABLE_TCL +# include +#endif + #define PRIVATE_NAMESPACE_BEGIN namespace { #define PRIVATE_NAMESPACE_END } #define YOSYS_NAMESPACE_BEGIN namespace Yosys { @@ -107,7 +111,6 @@ void yosys_setup(); void yosys_shutdown(); #ifdef YOSYS_ENABLE_TCL -#include Tcl_Interp *yosys_get_tcl_interp(); #endif From 2fdb3a4a91e2dc07f9aa75c478c6b8bfa1d1eb19 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 12 Oct 2014 13:48:05 +0200 Subject: [PATCH 045/492] Various Makefile changes for cross-compiling ABC for Win32 --- .gitignore | 1 + Makefile | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 90550863e..557240f0f 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ /yosys.exe /yosys.html /yosys-abc +/yosys-abc.exe /yosys-config /yosys-filterlib /yosys-filterlib.exe diff --git a/Makefile b/Makefile index 0eb5de2bc..8d121c8f2 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,7 @@ OBJS = kernel/version_$(GIT_REV).o # delete your work on ABC.. ABCREV = 4d547a5e065b ABCPULL = 1 +ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" define newline @@ -93,6 +94,8 @@ CXXFLAGS += -std=gnu++0x -Os -D_POSIX_SOURCE CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS)) LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s LDLIBS := $(filter-out -lrt,$(LDLIBS)) +ABCMKARGS += ARCHFLAGS="-DLIN -DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 -DSIZEOF_INT=4 -DWIN32_NO_DLL -x c++ -fpermissive -w -pthread" +ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib" READLINE=0 EXE = .exe else ifneq ($(CONFIG),none) @@ -126,7 +129,7 @@ endif ifeq ($(ENABLE_ABC),1) CXXFLAGS += -DYOSYS_ENABLE_ABC -TARGETS += yosys-abc +TARGETS += yosys-abc$(EXE) endif ifeq ($(ENABLE_VERIFIC),1) @@ -225,7 +228,7 @@ yosys-config: yosys-config.in -e 's,@BINDIR@,$(DESTDIR)/bin,;' -e 's,@DATDIR@,$(DESTDIR)/share/yosys,;' < yosys-config.in > yosys-config $(Q) chmod +x yosys-config -abc/abc-$(ABCREV): +abc/abc-$(ABCREV)$(EXE): $(P) ifneq ($(ABCREV),default) $(Q) if ( cd abc 2> /dev/null && hg identify; ) | grep -q +; then \ @@ -239,14 +242,14 @@ ifneq ($(ABCREV),default) fi endif $(Q) rm -f abc/abc-[0-9a-f]* - $(Q) cd abc && $(MAKE) $(S) PROG="abc-$(ABCREV)" MSG_PREFIX="$(eval P_OFFSET = 5)$(call P_SHOW)$(eval P_OFFSET = 10) ABC: " + $(Q) cd abc && $(MAKE) $(S) $(ABCMKARGS) PROG="abc-$(ABCREV)$(EXE)" MSG_PREFIX="$(eval P_OFFSET = 5)$(call P_SHOW)$(eval P_OFFSET = 10) ABC: " ifeq ($(ABCREV),default) -.PHONY: abc/abc-$(ABCREV) +.PHONY: abc/abc-$(ABCREV)$(EXE) endif -yosys-abc: abc/abc-$(ABCREV) - $(P) cp abc/abc-$(ABCREV) yosys-abc +yosys-abc$(EXE): abc/abc-$(ABCREV)$(EXE) + $(P) cp abc/abc-$(ABCREV)$(EXE) yosys-abc$(EXE) test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/simple && bash run-test.sh @@ -296,8 +299,8 @@ clean: rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d clean-abc: - make -C abc clean - rm -f yosys-abc abc/abc-[0-9a-f]* + $(MAKE) -C abc clean + rm -f yosys-abc$(EXE) abc/abc-[0-9a-f]* mrproper: clean git clean -xdf From 0913e968f59aed413dcb9bc5e392a554e2711ad7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 12 Oct 2014 14:48:19 +0200 Subject: [PATCH 046/492] More win32/abc fixes --- Makefile | 8 ++++-- kernel/yosys.cc | 12 ++++---- passes/abc/abc.cc | 71 ++++++++++++++++++++++------------------------- 3 files changed, 46 insertions(+), 45 deletions(-) diff --git a/Makefile b/Makefile index 8d121c8f2..ab7fc719b 100644 --- a/Makefile +++ b/Makefile @@ -95,7 +95,7 @@ CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS)) LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s LDLIBS := $(filter-out -lrt,$(LDLIBS)) ABCMKARGS += ARCHFLAGS="-DLIN -DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 -DSIZEOF_INT=4 -DWIN32_NO_DLL -x c++ -fpermissive -w -pthread" -ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib" READLINE=0 +ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" READLINE=0 EXE = .exe else ifneq ($(CONFIG),none) @@ -220,7 +220,7 @@ yosys$(EXE): $(OBJS) kernel/version_$(GIT_REV).cc: Makefile $(P) rm -f kernel/version_*.o kernel/version_*.d kernel/version_*.cc - $(Q) echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys $(YOSYS_VER) (git sha1 $(GIT_REV), $(CXX) ` \ + $(Q) echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys $(YOSYS_VER) (git sha1 $(GIT_REV), $(notdir $(CXX)) ` \ $(CXX) --version | tr ' ()' '\n' | grep '^[0-9]' | head -n1` $(filter -f% -m% -O% -DNDEBUG,$(CXXFLAGS)))\"; }" > kernel/version_$(GIT_REV).cc yosys-config: yosys-config.in @@ -315,8 +315,12 @@ qtcreator: ifeq ($(CONFIG),mxe) dist: $(TARGETS) $(EXTRA_TARGETS) rm -rf yosys-win32-$(YOSYS_VER) + rm -rf yosys-win32-$(YOSYS_VER).zip mkdir -p yosys-win32-$(YOSYS_VER) cp -r yosys.exe share/ yosys-win32-$(YOSYS_VER)/ +ifeq ($(ENABLE_ABC),1) + cp -r yosys-abc.exe abc/lib/x86/pthreadVC2.dll yosys-win32-$(YOSYS_VER)/ +endif echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-$(YOSYS_VER)/readme.txt echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-$(YOSYS_VER)/readme.txt zip -r yosys-win32-$(YOSYS_VER).zip yosys-win32-$(YOSYS_VER)/ diff --git a/kernel/yosys.cc b/kernel/yosys.cc index fa14c5d9a..e50bfcbe6 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -473,12 +473,14 @@ std::string proc_self_dirname() #elif defined(_WIN32) std::string proc_self_dirname() { - char path[MAX_PATH+1]; - if (!GetModuleFileName(0, path, MAX_PATH+1)) + char longpath[MAX_PATH+1], shortpath[MAX_PATH+1]; + if (!GetModuleFileName(0, longpath, MAX_PATH+1)) log_error("GetModuleFileName() failed.\n"); - for (int i = strlen(path)-1; i >= 0 && path[i] != '/' && path[i] != '\\' ; i--) - path[i] = 0; - return std::string(path); + if (!GetShortPathName(longpath, shortpath, MAX_PATH+1)) + log_error("GetShortPathName() failed.\n"); + for (int i = strlen(shortpath)-1; i >= 0 && shortpath[i] != '/' && shortpath[i] != '\\' ; i--) + shortpath[i] = 0; + return std::string(shortpath); } #elif defined(EMSCRIPTEN) std::string proc_self_dirname() diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index c63867068..891804393 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -559,39 +559,49 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin tempdir_name = make_temp_dir(tempdir_name); log_header("Extracting gate netlist of module `%s' to `%s/input.blif'..\n", module->name.c_str(), tempdir_name.c_str()); - std::string abc_command; + std::string abc_script = stringf("read_blif %s/input.blif; ", tempdir_name.c_str()); + + if (!liberty_file.empty()) { + abc_script += stringf("read_lib -w %s; ", liberty_file.c_str()); + if (!constr_file.empty()) + abc_script += stringf("read_constr -v %s; ", constr_file.c_str()); + } else + if (lut_mode) + abc_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); + else + abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str()); + if (!script_file.empty()) { if (script_file[0] == '+') { for (size_t i = 1; i < script_file.size(); i++) if (script_file[i] == '\'') - abc_command += "'\\''"; + abc_script += "'\\''"; else if (script_file[i] == ',') - abc_command += " "; + abc_script += " "; else - abc_command += script_file[i]; + abc_script += script_file[i]; } else - abc_command = stringf("source %s", script_file.c_str()); + abc_script += stringf("source %s", script_file.c_str()); } else if (lut_mode) - abc_command = fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; + abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; else if (!liberty_file.empty()) - abc_command = constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR); + abc_script += constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR); else - abc_command = fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL; + abc_script += fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL; - for (size_t pos = abc_command.find("{D}"); pos != std::string::npos; pos = abc_command.find("{D}", pos)) - abc_command = abc_command.substr(0, pos) + delay_target + abc_command.substr(pos+3); + for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos)) + abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3); - abc_command = add_echos_to_abc_cmd(abc_command); + abc_script += stringf("; write_blif %s/output.blif", tempdir_name.c_str()); + abc_script = add_echos_to_abc_cmd(abc_script); - if (abc_command.size() > 128) { - for (size_t i = 0; i+1 < abc_command.size(); i++) - if (abc_command[i] == ';' && abc_command[i+1] == ' ') - abc_command[i+1] = '\n'; - FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt"); - fprintf(f, "%s\n", abc_command.c_str()); - fclose(f); - abc_command = stringf("source %s/abc.script", tempdir_name.c_str()); - } + for (size_t i = 0; i+1 < abc_script.size(); i++) + if (abc_script[i] == ';' && abc_script[i+1] == ' ') + abc_script[i+1] = '\n'; + + FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt"); + fprintf(f, "%s\n", abc_script.c_str()); + fclose(f); if (clk_str.empty()) { if (clk_str[0] == '!') { @@ -652,7 +662,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin handle_loops(); std::string buffer = stringf("%s/input.blif", tempdir_name.c_str()); - FILE *f = fopen(buffer.c_str(), "wt"); + f = fopen(buffer.c_str(), "wt"); if (f == NULL) log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); @@ -793,23 +803,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin fclose(f); } - buffer = stringf("%s -s -c '", exe_file.c_str()); - if (!liberty_file.empty()) { - buffer += stringf("read_blif %s/input.blif; read_lib -w %s; ", - tempdir_name.c_str(), liberty_file.c_str()); - if (!constr_file.empty()) - buffer += stringf("read_constr -v %s; ", constr_file.c_str()); - buffer += abc_command + "; "; - } else - if (lut_mode) - buffer += stringf("read_blif %s/input.blif; read_lut %s/lutdefs.txt; %s; ", - tempdir_name.c_str(), tempdir_name.c_str(), abc_command.c_str()); - else - buffer += stringf("read_blif %s/input.blif; read_library %s/stdcells.genlib; %s; ", - tempdir_name.c_str(), tempdir_name.c_str(), abc_command.c_str()); - buffer += stringf("write_blif %s/output.blif' 2>&1", tempdir_name.c_str()); - - log("%s\n", buffer.c_str()); + buffer = stringf("%s -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str()); + log("Running ABC command: %s\n", buffer.c_str()); abc_output_filter filt; int ret = run_command(buffer, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1)); From 09d2e5cf5d2b7d391975ba4c5524f03543f05a48 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 12 Oct 2014 15:02:40 +0200 Subject: [PATCH 047/492] Fixed ABC ARCHFLAGS for win32 cross build --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ab7fc719b..cbfebdf02 100644 --- a/Makefile +++ b/Makefile @@ -94,7 +94,7 @@ CXXFLAGS += -std=gnu++0x -Os -D_POSIX_SOURCE CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS)) LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s LDLIBS := $(filter-out -lrt,$(LDLIBS)) -ABCMKARGS += ARCHFLAGS="-DLIN -DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 -DSIZEOF_INT=4 -DWIN32_NO_DLL -x c++ -fpermissive -w -pthread" +ABCMKARGS += ARCHFLAGS="-DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 -DSIZEOF_INT=4 -DWIN32_NO_DLL -x c++ -fpermissive -w" ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" READLINE=0 EXE = .exe From c21c9dab1e791f5c71f48ec3303fbb7cedee8a1a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 13 Oct 2014 17:22:06 +0200 Subject: [PATCH 048/492] Removed CHECK() macro from libparse.cc (was using non-std c features) --- passes/techmap/libparse.cc | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc index bf170d74c..50d31ab5a 100644 --- a/passes/techmap/libparse.cc +++ b/passes/techmap/libparse.cc @@ -244,21 +244,6 @@ void LibertyParser::error() /**** BEGIN: http://svn.clifford.at/tools/trunk/examples/check.h ****/ -// This is to not confuse the VIM syntax highlighting -#define CHECK_VAL_OPEN ( -#define CHECK_VAL_CLOSE ) - -#define CHECK(result, check) \ - CHECK_VAL_OPEN{ \ - auto _R = (result); \ - if (!(_R check)) { \ - fprintf(stderr, "Error from '%s' (%ld %s) in %s:%d.\n", \ - #result, (long int)_R, #check, __FILE__, __LINE__); \ - abort(); \ - } \ - _R; \ - }CHECK_VAL_CLOSE - #define CHECK_NV(result, check) \ do { \ auto _R = (result); \ @@ -280,6 +265,14 @@ void LibertyParser::error() /**** END: http://svn.clifford.at/tools/trunk/examples/check.h ****/ +LibertyAst *find_non_null(LibertyAst *node, const char *name) +{ + LibertyAst *ret = node->find(name); + if (ret == NULL) + fprintf(stderr, "Error: expected to find `%s' node.\n", name); + return ret; +} + std::string func2vl(std::string str) { for (size_t pos = str.find_first_of("\" \t"); pos != std::string::npos; pos = str.find_first_of("\" \t")) { @@ -388,7 +381,7 @@ void gen_verilogsim_cell(LibertyAst *ast) if (child->id != "pin") continue; CHECK_NV(child->args.size(), == 1); - LibertyAst *dir = CHECK(child->find("direction"), != NULL); + LibertyAst *dir = find_non_null(child, "direction"); LibertyAst *func = child->find("function"); printf(" %s %s;\n", dir->value.c_str(), child->args[0].c_str()); if (func != NULL) @@ -428,8 +421,8 @@ void gen_verilogsim_cell(LibertyAst *ast) const char *else_prefix = ""; if (!clear_expr.empty() && !preset_expr.empty()) { printf(" %sif ((%s) && (%s)) begin\n", else_prefix, clear_expr.c_str(), preset_expr.c_str()); - clear_preset_var(iq_var, CHECK(child->find("clear_preset_var1"), != NULL)->value); - clear_preset_var(iqn_var, CHECK(child->find("clear_preset_var2"), != NULL)->value); + clear_preset_var(iq_var, find_non_null(child, "clear_preset_var1")->value); + clear_preset_var(iqn_var, find_non_null(child, "clear_preset_var2")->value); printf(" end\n"); else_prefix = "else "; } @@ -449,7 +442,7 @@ void gen_verilogsim_cell(LibertyAst *ast) } if (*else_prefix) printf(" %sbegin\n", else_prefix); - std::string expr = CHECK(child->find("next_state"), != NULL)->value; + std::string expr = find_non_null(child, "next_state")->value; printf(" // %s\n", expr.c_str()); printf(" %s <= %s;\n", iq_var.c_str(), func2vl(expr).c_str()); printf(" %s <= ~(%s);\n", iqn_var.c_str(), func2vl(expr).c_str()); @@ -481,8 +474,8 @@ void gen_verilogsim_cell(LibertyAst *ast) const char *else_prefix = ""; if (!clear_expr.empty() && !preset_expr.empty()) { printf(" %sif ((%s) && (%s)) begin\n", else_prefix, clear_expr.c_str(), preset_expr.c_str()); - clear_preset_var(iq_var, CHECK(child->find("clear_preset_var1"), != NULL)->value); - clear_preset_var(iqn_var, CHECK(child->find("clear_preset_var2"), != NULL)->value); + clear_preset_var(iq_var, find_non_null(child, "clear_preset_var1")->value); + clear_preset_var(iqn_var, find_non_null(child, "clear_preset_var2")->value); printf(" end\n"); else_prefix = "else "; } @@ -502,7 +495,7 @@ void gen_verilogsim_cell(LibertyAst *ast) } if (!enable_expr.empty()) { printf(" %sif (%s) begin\n", else_prefix, enable_expr.c_str()); - std::string expr = CHECK(child->find("data_in"), != NULL)->value; + std::string expr = find_non_null(child, "data_in")->value; printf(" %s <= %s;\n", iq_var.c_str(), func2vl(expr).c_str()); printf(" %s <= ~(%s);\n", iqn_var.c_str(), func2vl(expr).c_str()); printf(" end\n"); From 2873a8444ee5dbd0a3d034fb4a7a877c680be45d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 15 Oct 2014 00:41:14 +0200 Subject: [PATCH 049/492] Updated ABC, enabled ABC in mxe builds --- Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index cbfebdf02..f408c40fd 100644 --- a/Makefile +++ b/Makefile @@ -56,9 +56,9 @@ OBJS = kernel/version_$(GIT_REV).o # is just a symlink to your actual ABC working directory, as 'make mrproper' # will remove the 'abc' directory and you do not want to accidentally # delete your work on ABC.. -ABCREV = 4d547a5e065b +ABCREV = 930a4de962a1 ABCPULL = 1 -ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" +ABCMKARGS = # CC="$(CXX)" CXX="$(CXX)" define newline @@ -348,7 +348,6 @@ config-emcc: clean config-mxe: clean echo 'CONFIG := mxe' > Makefile.conf echo 'ENABLE_TCL := 0' >> Makefile.conf - echo 'ENABLE_ABC := 0' >> Makefile.conf echo 'ENABLE_PLUGINS := 0' >> Makefile.conf config-gprof: clean From fad0b0c506f2d7cb1158a3dac53139b8dec7a04e Mon Sep 17 00:00:00 2001 From: William Speirs Date: Tue, 14 Oct 2014 17:06:02 -0400 Subject: [PATCH 050/492] Updated lexers & parsers to include prefixes --- frontends/ilang/Makefile.inc | 22 ++++++++--------- frontends/ilang/{lexer.l => ilang_lexer.l} | 8 +++++-- frontends/ilang/{parser.y => ilang_parser.y} | 0 frontends/verilog/Makefile.inc | 24 +++++++++---------- .../verilog/{lexer.l => verilog_lexer.l} | 8 +++++-- .../verilog/{parser.y => verilog_parser.y} | 0 6 files changed, 35 insertions(+), 27 deletions(-) rename frontends/ilang/{lexer.l => ilang_lexer.l} (95%) rename frontends/ilang/{parser.y => ilang_parser.y} (100%) rename frontends/verilog/{lexer.l => verilog_lexer.l} (98%) rename frontends/verilog/{parser.y => verilog_parser.y} (100%) diff --git a/frontends/ilang/Makefile.inc b/frontends/ilang/Makefile.inc index e832cfed8..984d436c6 100644 --- a/frontends/ilang/Makefile.inc +++ b/frontends/ilang/Makefile.inc @@ -1,18 +1,18 @@ -GENFILES += frontends/ilang/parser.tab.cc -GENFILES += frontends/ilang/parser.tab.h -GENFILES += frontends/ilang/parser.output -GENFILES += frontends/ilang/lexer.cc +GENFILES += frontends/ilang/ilang_parser.tab.cc +GENFILES += frontends/ilang/ilang_parser.tab.h +GENFILES += frontends/ilang/ilang_parser.output +GENFILES += frontends/ilang/ilang_lexer.cc -frontends/ilang/parser.tab.cc: frontends/ilang/parser.y - $(P) bison -d -r all -b frontends/ilang/parser frontends/ilang/parser.y - $(Q) mv frontends/ilang/parser.tab.c frontends/ilang/parser.tab.cc +frontends/ilang/ilang_parser.tab.cc: frontends/ilang/ilang_parser.y + $(P) bison -d -r all -b frontends/ilang/ilang_parser frontends/ilang/ilang_parser.y + $(Q) mv frontends/ilang/ilang_parser.tab.c frontends/ilang/ilang_parser.tab.cc -frontends/ilang/parser.tab.h: frontends/ilang/parser.tab.cc +frontends/ilang/ilang_parser.tab.h: frontends/ilang/ilang_parser.tab.cc -frontends/ilang/lexer.cc: frontends/ilang/lexer.l - $(P) flex -o frontends/ilang/lexer.cc frontends/ilang/lexer.l +frontends/ilang/ilang_lexer.cc: frontends/ilang/ilang_lexer.l + $(P) flex -o frontends/ilang/ilang_lexer.cc frontends/ilang/ilang_lexer.l -OBJS += frontends/ilang/parser.tab.o frontends/ilang/lexer.o +OBJS += frontends/ilang/ilang_parser.tab.o frontends/ilang/ilang_lexer.o OBJS += frontends/ilang/ilang_frontend.o diff --git a/frontends/ilang/lexer.l b/frontends/ilang/ilang_lexer.l similarity index 95% rename from frontends/ilang/lexer.l rename to frontends/ilang/ilang_lexer.l index 9669f0924..dcbc6b6d7 100644 --- a/frontends/ilang/lexer.l +++ b/frontends/ilang/ilang_lexer.l @@ -30,12 +30,16 @@ #endif #include "ilang_frontend.h" -#include "parser.tab.h" +#include "ilang_parser.tab.h" USING_YOSYS_NAMESPACE #define YY_INPUT(buf,result,max_size) \ - result = readsome(*ILANG_FRONTEND::lexin, buf, max_size); + do { \ + ILANG_FRONTEND::lexin->read(buf, max_size-1); \ + result = ILANG_FRONTEND::lexin->gcount(); \ + if (result >= 0) buf[result] = '\0'; \ + } while (0) %} diff --git a/frontends/ilang/parser.y b/frontends/ilang/ilang_parser.y similarity index 100% rename from frontends/ilang/parser.y rename to frontends/ilang/ilang_parser.y diff --git a/frontends/verilog/Makefile.inc b/frontends/verilog/Makefile.inc index 49eb320ec..1b6854bb5 100644 --- a/frontends/verilog/Makefile.inc +++ b/frontends/verilog/Makefile.inc @@ -1,20 +1,20 @@ -GENFILES += frontends/verilog/parser.tab.cc -GENFILES += frontends/verilog/parser.tab.h -GENFILES += frontends/verilog/parser.output -GENFILES += frontends/verilog/lexer.cc +GENFILES += frontends/verilog/verilog_parser.tab.cc +GENFILES += frontends/verilog/verilog_parser.tab.h +GENFILES += frontends/verilog/verilog_parser.output +GENFILES += frontends/verilog/verilog_lexer.cc -frontends/verilog/parser.tab.cc: frontends/verilog/parser.y - $(P) bison -d -r all -b frontends/verilog/parser frontends/verilog/parser.y - $(Q) mv frontends/verilog/parser.tab.c frontends/verilog/parser.tab.cc +frontends/verilog/verilog_parser.tab.cc: frontends/verilog/verilog_parser.y + $(P) bison -d -r all -b frontends/verilog/verilog_parser frontends/verilog/verilog_parser.y + $(Q) mv frontends/verilog/verilog_parser.tab.c frontends/verilog/verilog_parser.tab.cc -frontends/verilog/parser.tab.h: frontends/verilog/parser.tab.cc +frontends/verilog/verilog_parser.tab.h: frontends/verilog/verilog_parser.tab.cc -frontends/verilog/lexer.cc: frontends/verilog/lexer.l - $(P) flex -o frontends/verilog/lexer.cc frontends/verilog/lexer.l +frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l + $(P) flex -o frontends/verilog/verilog_lexer.cc frontends/verilog/verilog_lexer.l -OBJS += frontends/verilog/parser.tab.o -OBJS += frontends/verilog/lexer.o +OBJS += frontends/verilog/verilog_parser.tab.o +OBJS += frontends/verilog/verilog_lexer.o OBJS += frontends/verilog/preproc.o OBJS += frontends/verilog/verilog_frontend.o OBJS += frontends/verilog/const2ast.o diff --git a/frontends/verilog/lexer.l b/frontends/verilog/verilog_lexer.l similarity index 98% rename from frontends/verilog/lexer.l rename to frontends/verilog/verilog_lexer.l index 98f360885..0d28e2e7f 100644 --- a/frontends/verilog/lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -42,7 +42,7 @@ #include "kernel/log.h" #include "verilog_frontend.h" #include "frontends/ast/ast.h" -#include "parser.tab.h" +#include "verilog_parser.tab.h" USING_YOSYS_NAMESPACE using namespace AST; @@ -64,7 +64,11 @@ YOSYS_NAMESPACE_END return TOK_ID; #define YY_INPUT(buf,result,max_size) \ - result = readsome(*lexin, buf, max_size); + do { \ + lexin->read(buf, max_size-1); \ + result = lexin->gcount(); \ + if (result >= 0) buf[result] = '\0'; \ + } while (0) %} diff --git a/frontends/verilog/parser.y b/frontends/verilog/verilog_parser.y similarity index 100% rename from frontends/verilog/parser.y rename to frontends/verilog/verilog_parser.y From 0352dbfd65072f42824852b2f5b925e7d9865a90 Mon Sep 17 00:00:00 2001 From: William Speirs Date: Tue, 14 Oct 2014 17:07:30 -0400 Subject: [PATCH 051/492] Fixed log so it will compile under Visual Studio - Included an implementation of gettimeofday --- kernel/log.cc | 25 ++++++++++++++++++++++++- kernel/log.h | 22 +++++++++++++++------- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/kernel/log.cc b/kernel/log.cc index 87a75410d..4585e7eff 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -21,7 +21,10 @@ #include "libs/sha1/sha1.h" #include "backends/ilang/ilang_backend.h" -#include +#ifndef _WIN32 + #include +#endif + #include #include #include @@ -48,6 +51,26 @@ static struct timeval initial_tv = { 0, 0 }; static bool next_print_log = false; static int log_newline_count = 0; +#ifdef _WIN32 +// this will get time information and return it in timeval, simulating gettimeofday() +int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + LARGE_INTEGER counter; + LARGE_INTEGER freq; + + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&counter); + + counter.QuadPart *= 1000000; + counter.QuadPart /= freq.QuadPart; + + tv->tv_sec = counter.QuadPart / 1000000; + tv->tv_usec = counter.QuadPart % 1000000; + + return 0; +} +#endif + void logv(const char *format, va_list ap) { while (format[0] == '\n' && format[1] != 0) { diff --git a/kernel/log.h b/kernel/log.h index b4182b5f3..d4b21110c 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -23,10 +23,10 @@ #define LOG_H #include -#include #ifndef _WIN32 -# include + #include + #include #endif // from libs/sha1/sha1.h @@ -51,12 +51,20 @@ extern int log_verbose_level; void logv(const char *format, va_list ap); void logv_header(const char *format, va_list ap); -void logv_error(const char *format, va_list ap) __attribute__ ((noreturn)); -void log(const char *format, ...) __attribute__ ((format (printf, 1, 2))); -void log_header(const char *format, ...) __attribute__ ((format (printf, 1, 2))); -void log_error(const char *format, ...) __attribute__ ((format (printf, 1, 2))) __attribute__ ((noreturn)); -void log_cmd_error(const char *format, ...) __attribute__ ((format (printf, 1, 2))) __attribute__ ((noreturn)); +#if !defined(__GNUC__) && !defined(__clang__) + void logv_error(const char *format, va_list ap); + void log(const char *format, ...); + void log_header(const char *format, ...); + void log_error(const char *format, ...); + void log_cmd_error(const char *format, ...); +#else + void logv_error(const char *format, va_list ap) __attribute__((noreturn)); + void log(const char *format, ...) __attribute__((format(printf, 1, 2))); + void log_header(const char *format, ...) __attribute__((format(printf, 1, 2))); + void log_error(const char *format, ...) __attribute__((format(printf, 1, 2))) __attribute__((noreturn)); + void log_cmd_error(const char *format, ...) __attribute__((format(printf, 1, 2))) __attribute__((noreturn)); +#endif void log_spacer(); void log_push(); From 069521e2d5d5568739c7e8d7db31859bb88965a6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 15 Oct 2014 00:56:04 +0200 Subject: [PATCH 052/492] Define empty __attribute__ macro for non-gcc, non-clang compilers --- kernel/log.h | 18 +++++------------- kernel/yosys.h | 4 ++++ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/kernel/log.h b/kernel/log.h index d4b21110c..e0c8f7ba0 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -52,19 +52,11 @@ extern int log_verbose_level; void logv(const char *format, va_list ap); void logv_header(const char *format, va_list ap); -#if !defined(__GNUC__) && !defined(__clang__) - void logv_error(const char *format, va_list ap); - void log(const char *format, ...); - void log_header(const char *format, ...); - void log_error(const char *format, ...); - void log_cmd_error(const char *format, ...); -#else - void logv_error(const char *format, va_list ap) __attribute__((noreturn)); - void log(const char *format, ...) __attribute__((format(printf, 1, 2))); - void log_header(const char *format, ...) __attribute__((format(printf, 1, 2))); - void log_error(const char *format, ...) __attribute__((format(printf, 1, 2))) __attribute__((noreturn)); - void log_cmd_error(const char *format, ...) __attribute__((format(printf, 1, 2))) __attribute__((noreturn)); -#endif +void logv_error(const char *format, va_list ap) __attribute__((noreturn)); +void log(const char *format, ...) __attribute__((format(printf, 1, 2))); +void log_header(const char *format, ...) __attribute__((format(printf, 1, 2))); +void log_error(const char *format, ...) __attribute__((format(printf, 1, 2))) __attribute__((noreturn)); +void log_cmd_error(const char *format, ...) __attribute__((format(printf, 1, 2))) __attribute__((noreturn)); void log_spacer(); void log_push(); diff --git a/kernel/yosys.h b/kernel/yosys.h index 5a37dd3c5..37d3e52f4 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -77,6 +77,10 @@ # define FINAL #endif +#if !defined(__GNUC__) && !defined(__clang__) +# define __attribute__(...) +#endif + YOSYS_NAMESPACE_BEGIN namespace RTLIL { From 9cb230379901da89649676d4a2752bde59c09f59 Mon Sep 17 00:00:00 2001 From: William Speirs Date: Tue, 14 Oct 2014 17:10:08 -0400 Subject: [PATCH 053/492] Made iterators extend std::iterator and added == operator --- kernel/rtlil.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 8df0bfe19..5629c8652 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -920,23 +920,25 @@ struct RTLIL::SigBit } }; -struct RTLIL::SigSpecIterator +struct RTLIL::SigSpecIterator : public std::iterator { RTLIL::SigSpec *sig_p; int index; inline RTLIL::SigBit &operator*() const; inline bool operator!=(const RTLIL::SigSpecIterator &other) const { return index != other.index; } + inline bool operator==(const RTLIL::SigSpecIterator &other) const { return index == other.index; } inline void operator++() { index++; } }; -struct RTLIL::SigSpecConstIterator +struct RTLIL::SigSpecConstIterator : public std::iterator { const RTLIL::SigSpec *sig_p; int index; inline const RTLIL::SigBit &operator*() const; inline bool operator!=(const RTLIL::SigSpecConstIterator &other) const { return index != other.index; } + inline bool operator==(const RTLIL::SigSpecIterator &other) const { return index == other.index; } inline void operator++() { index++; } }; From 6433203b39f830a5c0d80347f14ab341ef3921ce Mon Sep 17 00:00:00 2001 From: William Speirs Date: Tue, 14 Oct 2014 17:10:53 -0400 Subject: [PATCH 054/492] Wrapped init in std::set constructor --- passes/opt/wreduce.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 89b1f8856..8f59a041e 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -32,14 +32,14 @@ struct WreduceConfig WreduceConfig() { - supported_cell_types = { + supported_cell_types = std::set({ "$not", "$pos", "$neg", "$and", "$or", "$xor", "$xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", "$add", "$sub", // "$mul", "$div", "$mod", "$pow", "$mux", "$pmux" - }; + }); } }; From 9ee3a4b94fa78ad2ccf4178d7a49bc659df29cb1 Mon Sep 17 00:00:00 2001 From: William Speirs Date: Tue, 14 Oct 2014 17:15:08 -0400 Subject: [PATCH 055/492] Changed to explicit heap allocated memory --- libs/sha1/sha1.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/sha1/sha1.cpp b/libs/sha1/sha1.cpp index dc86b2ce2..825274b9b 100644 --- a/libs/sha1/sha1.cpp +++ b/libs/sha1/sha1.cpp @@ -256,9 +256,12 @@ void SHA1::buffer_to_block(const std::string &buffer, uint32 block[BLOCK_BYTES]) void SHA1::read(std::istream &is, std::string &s, int max) { - char sbuf[max]; + char* sbuf = new char[max]; + is.read(sbuf, max); s.assign(sbuf, is.gcount()); + + delete[] sbuf; } From e5b8390f44be7d300fdf32193fa58b76ba448072 Mon Sep 17 00:00:00 2001 From: William Speirs Date: Tue, 14 Oct 2014 17:15:35 -0400 Subject: [PATCH 056/492] Changed from "and" to "&&" --- passes/fsm/fsm_opt.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/fsm/fsm_opt.cc b/passes/fsm/fsm_opt.cc index 6685e8e0e..4b93d79f9 100644 --- a/passes/fsm/fsm_opt.cc +++ b/passes/fsm/fsm_opt.cc @@ -342,7 +342,7 @@ struct FsmOptPass : public Pass { for (auto &mod_it : design->modules_) { if (design->selected(mod_it.second)) for (auto &cell_it : mod_it.second->cells_) - if (cell_it.second->type == "$fsm" and design->selected(mod_it.second, cell_it.second)) + if (cell_it.second->type == "$fsm" && design->selected(mod_it.second, cell_it.second)) FsmData::optimize_fsm(cell_it.second, mod_it.second); } } From cf85aab62f961c905e4691fde59af774053d3d58 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 15 Oct 2014 01:05:08 +0200 Subject: [PATCH 057/492] A few indent fixes --- kernel/log.cc | 2 +- kernel/log.h | 4 ++-- libs/sha1/sha1.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/log.cc b/kernel/log.cc index 4585e7eff..2cae6a636 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -22,7 +22,7 @@ #include "backends/ilang/ilang_backend.h" #ifndef _WIN32 - #include +# include #endif #include diff --git a/kernel/log.h b/kernel/log.h index e0c8f7ba0..904ba4759 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -25,8 +25,8 @@ #include #ifndef _WIN32 - #include - #include +# include +# include #endif // from libs/sha1/sha1.h diff --git a/libs/sha1/sha1.cpp b/libs/sha1/sha1.cpp index 825274b9b..883d42837 100644 --- a/libs/sha1/sha1.cpp +++ b/libs/sha1/sha1.cpp @@ -261,7 +261,7 @@ void SHA1::read(std::istream &is, std::string &s, int max) is.read(sbuf, max); s.assign(sbuf, is.gcount()); - delete[] sbuf; + delete[] sbuf; } From c3e9922b5d871269bf4ee33da24318d3b5199ac3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 15 Oct 2014 01:12:53 +0200 Subject: [PATCH 058/492] Replaced readsome() with read() and gcount() --- frontends/verilog/preproc.cc | 8 +++++--- kernel/yosys.cc | 16 ---------------- kernel/yosys.h | 1 - passes/cmds/write_file.cc | 9 ++++++--- 4 files changed, 11 insertions(+), 23 deletions(-) diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index b4e77c31b..da658410d 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -196,14 +196,16 @@ static std::string next_token(bool pass_newline = false) static void input_file(std::istream &f, std::string filename) { char buffer[513]; - int rc; insert_input(""); auto it = input_buffer.begin(); input_buffer.insert(it, "`file_push " + filename + "\n"); - while ((rc = readsome(f, buffer, sizeof(buffer)-1)) > 0) { - buffer[rc] = 0; + while (1) { + f.read(buffer, sizeof(buffer)-1); + if (f.gcount() <= 0) + break; + buffer[f.gcount()] = 0; input_buffer.insert(it, buffer); } input_buffer.insert(it, "\n`file_pop\n"); diff --git a/kernel/yosys.cc b/kernel/yosys.cc index e50bfcbe6..ba3049c53 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -172,22 +172,6 @@ bool patmatch(const char *pattern, const char *string) return false; } -int readsome(std::istream &f, char *s, int n) -{ - int rc = f.readsome(s, n); - - // win32 sometimes returns 0 on a non-empty stream.. - if (rc == 0) { - int c = f.get(); - if (c != EOF) { - *s = c; - rc = 1; - } - } - - return rc; -} - int run_command(const std::string &command, std::function process_line) { if (!process_line) diff --git a/kernel/yosys.h b/kernel/yosys.h index 37d3e52f4..83230cbfb 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -94,7 +94,6 @@ std::string stringf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)) std::string vstringf(const char *fmt, va_list ap); std::string next_token(std::string &text, const char *sep); bool patmatch(const char *pattern, const char *string); -int readsome(std::istream &f, char *s, int n); int run_command(const std::string &command, std::function process_line = std::function()); std::string make_temp_file(std::string template_str = "/tmp/yosys_XXXXXX"); std::string make_temp_dir(std::string template_str = "/tmp/yosys_XXXXXX"); diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc index 3f4419724..9bf1a75a8 100644 --- a/passes/cmds/write_file.cc +++ b/passes/cmds/write_file.cc @@ -68,10 +68,13 @@ struct WriteFileFrontend : public Frontend { FILE *of = fopen(output_filename.c_str(), append_mode ? "a" : "w"); char buffer[64 * 1024]; - size_t bytes; - while (0 < (bytes = readsome(*f, buffer, sizeof(buffer)))) - fwrite(buffer, bytes, 1, of); + while (1) { + f->read(buffer, sizeof(buffer)); + if (f->gcount() <= 0) + break; + fwrite(buffer, f->gcount(), 1, of); + } fclose(of); } From f65e1c309fbfd0eae719270bfc8b6887c9e05d9e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 15 Oct 2014 01:14:38 +0200 Subject: [PATCH 059/492] Updated .gitignore file for ilang and verilog frontends --- frontends/ilang/.gitignore | 8 ++++---- frontends/verilog/.gitignore | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frontends/ilang/.gitignore b/frontends/ilang/.gitignore index 72b06b0bf..43106a814 100644 --- a/frontends/ilang/.gitignore +++ b/frontends/ilang/.gitignore @@ -1,4 +1,4 @@ -lexer.cc -parser.output -parser.tab.cc -parser.tab.h +ilang_lexer.cc +ilang_parser.output +ilang_parser.tab.cc +ilang_parser.tab.h diff --git a/frontends/verilog/.gitignore b/frontends/verilog/.gitignore index 72b06b0bf..1d4ae9e5c 100644 --- a/frontends/verilog/.gitignore +++ b/frontends/verilog/.gitignore @@ -1,4 +1,4 @@ -lexer.cc -parser.output -parser.tab.cc -parser.tab.h +verilog_lexer.cc +verilog_parser.output +verilog_parser.tab.cc +verilog_parser.tab.h From 1fc6208ec05af672c7c6b7973b0eba1295bca5f4 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 15 Oct 2014 01:18:31 +0200 Subject: [PATCH 060/492] Check for _YOSYS_ in yosys.h --- kernel/yosys.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/yosys.h b/kernel/yosys.h index 83230cbfb..239146d77 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -58,6 +58,12 @@ #include #include +#ifndef _YOSYS_ +# error It looks like you are trying to build Yosys with the config defines set. \ + When building Yosys with a custom make system, make sure you set all the \ + defines the Yosys Makefile would set for your build configuration. +#endif + #ifdef YOSYS_ENABLE_TCL # include #endif From 3445a933a5f2c23b697b96948f44fb1b2012dbdb Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 15 Oct 2014 02:43:50 +0200 Subject: [PATCH 061/492] Fixed MXE build --- Makefile | 2 +- kernel/log.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index f408c40fd..a43f378e1 100644 --- a/Makefile +++ b/Makefile @@ -95,7 +95,7 @@ CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS)) LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s LDLIBS := $(filter-out -lrt,$(LDLIBS)) ABCMKARGS += ARCHFLAGS="-DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 -DSIZEOF_INT=4 -DWIN32_NO_DLL -x c++ -fpermissive -w" -ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" READLINE=0 +ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" READLINE=0 CC="$(CXX)" CXX="$(CXX)" EXE = .exe else ifneq ($(CONFIG),none) diff --git a/kernel/log.cc b/kernel/log.cc index 2cae6a636..19eb38c73 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -21,7 +21,7 @@ #include "libs/sha1/sha1.h" #include "backends/ilang/ilang_backend.h" -#ifndef _WIN32 +#if !defined(_WIN32) || defined(__MINGW32__) # include #endif @@ -51,7 +51,7 @@ static struct timeval initial_tv = { 0, 0 }; static bool next_print_log = false; static int log_newline_count = 0; -#ifdef _WIN32 +#if defined(_WIN32) && !defined(__MINGW32__) // this will get time information and return it in timeval, simulating gettimeofday() int gettimeofday(struct timeval *tv, struct timezone *tz) { From 2355ddf75d094e9272184ddd9ea916be49102b1b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 15 Oct 2014 02:48:51 +0200 Subject: [PATCH 062/492] Fixed gcc warning --- kernel/yosys.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index ba3049c53..1ce7b5207 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -252,7 +252,8 @@ std::string make_temp_dir(std::string template_str) log_assert(suffixlen == 0); char *p = strdup(template_str.c_str()); - mkdtemp(p); + p = mkdtemp(p); + log_assert(p != NULL); template_str = p; free(p); From 82ed814fa1d0e8e58392210976069daa4faa3f4a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 15 Oct 2014 20:36:32 +0200 Subject: [PATCH 063/492] Replaced log_assert() do { ... } while (0) hack with a static inline function --- kernel/log.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/log.h b/kernel/log.h index 904ba4759..421c50d3f 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -74,8 +74,12 @@ template static inline const char *log_id(T *obj) { void log_cell(RTLIL::Cell *cell, std::string indent = ""); +static inline void log_assert_worker(bool cond, const char *expr, const char *file, int line) { + if (!cond) log_error("Assert `%s' failed in %s:%d.\n", expr, file, line); +} + #define log_abort() YOSYS_NAMESPACE_PREFIX log_error("Abort in %s:%d.\n", __FILE__, __LINE__) -#define log_assert(_assert_expr_) do { if (_assert_expr_) break; YOSYS_NAMESPACE_PREFIX log_error("Assert `%s' failed in %s:%d.\n", #_assert_expr_, __FILE__, __LINE__); } while (0) +#define log_assert(_assert_expr_) YOSYS_NAMESPACE_PREFIX log_assert_worker(_assert_expr_, #_assert_expr_, __FILE__, __LINE__) #define log_ping() YOSYS_NAMESPACE_PREFIX log("-- %s:%d %s --\n", __FILE__, __LINE__, __PRETTY_FUNCTION__) From 6b05a9e8075af923c67ec3bb1b74573294ac8838 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 16 Oct 2014 00:44:23 +0200 Subject: [PATCH 064/492] Fixed handling of invalid array access in mem2reg code --- frontends/ast/ast.h | 1 + frontends/ast/simplify.cc | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 0a4016736..56f5d888d 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -209,6 +209,7 @@ namespace AST void mem2reg_as_needed_pass1(std::map> &mem2reg_places, std::map &mem2reg_flags, std::map &proc_flags, uint32_t &status_flags); void mem2reg_as_needed_pass2(std::set &mem2reg_set, AstNode *mod, AstNode *block); + bool mem2reg_check(std::set &mem2reg_set); void meminfo(int &mem_width, int &mem_size, int &addr_bits); // additional functionality for evaluating constant functions diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 9f33ea780..7e15283c4 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2179,14 +2179,25 @@ void AstNode::mem2reg_as_needed_pass1(std::map> } } +bool AstNode::mem2reg_check(std::set &mem2reg_set) +{ + if (type != AST_IDENTIFIER || !id2ast || !mem2reg_set.count(id2ast)) + return false; + + if (children.empty() || children[0]->type != AST_RANGE || GetSize(children[0]->children) != 1) + log_error("Invalid array access at %s:%d.\n", filename.c_str(), linenum); + + return true; +} + // actually replace memories with registers void AstNode::mem2reg_as_needed_pass2(std::set &mem2reg_set, AstNode *mod, AstNode *block) { if (type == AST_BLOCK) block = this; - if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && block != NULL && children[0]->id2ast && - mem2reg_set.count(children[0]->id2ast) > 0 && children[0]->children[0]->children[0]->type != AST_CONSTANT) + if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && block != NULL && + children[0]->mem2reg_check(mem2reg_set) && children[0]->children[0]->children[0]->type != AST_CONSTANT) { std::stringstream sstr; sstr << "$mem2reg_wr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++); @@ -2242,7 +2253,7 @@ void AstNode::mem2reg_as_needed_pass2(std::set &mem2reg_set, AstNode * type = AST_ASSIGN_EQ; } - if (type == AST_IDENTIFIER && id2ast && mem2reg_set.count(id2ast) > 0) + if (mem2reg_check(mem2reg_set)) { AstNode *bit_part_sel = NULL; if (children.size() == 2) From 3be5fa053f61a29039ed99876d3e89406c99cb7d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 16 Oct 2014 00:54:14 +0200 Subject: [PATCH 065/492] Fixed RTLIL::SigSpec::parse() for out-of-range bit- and part-selects --- kernel/rtlil.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 28f0dfdc5..5a94008d8 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2980,7 +2980,10 @@ bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::stri sigspec_parse_split(index_tokens, indices.substr(1, indices.size()-2), ':'); if (index_tokens.size() == 1) { cover("kernel.rtlil.sigspec.parse.bit_sel"); - sig.append(RTLIL::SigSpec(wire, atoi(index_tokens.at(0).c_str()))); + int a = atoi(index_tokens.at(0).c_str()); + if (a < 0 || a >= wire->width) + return false; + sig.append(RTLIL::SigSpec(wire, a)); } else { cover("kernel.rtlil.sigspec.parse.part_sel"); int a = atoi(index_tokens.at(0).c_str()); @@ -2989,6 +2992,10 @@ bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::stri int tmp = a; a = b, b = tmp; } + if (a < 0 || a >= wire->width) + return false; + if (b < 0 || b >= wire->width) + return false; sig.append(RTLIL::SigSpec(wire, a, b-a+1)); } } else From 3838856a9ee6debb05f39ad2c17d2eba95afd329 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 16 Oct 2014 10:31:54 +0200 Subject: [PATCH 066/492] Print "SystemVerilog" in "read_verilog -sv" log messages --- frontends/verilog/verilog_frontend.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 1e1cd852a..23d35f682 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -257,7 +257,7 @@ struct VerilogFrontend : public Frontend { } extra_args(f, filename, args, argidx); - log("Parsing Verilog input from `%s' to AST representation.\n", filename.c_str()); + log("Parsing %s input from `%s' to AST representation.\n", sv_mode ? "SystemVerilog" : "Verilog", filename.c_str()); AST::current_filename = filename; AST::set_line_num = &frontend_verilog_yyset_lineno; From 66eb254fc2595a6dcd94b439b0b287cc59c47270 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 16 Oct 2014 11:46:57 +0200 Subject: [PATCH 067/492] Some cleanups in opt_clean --- passes/opt/opt_clean.cc | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index c0b8853a6..4194f88c3 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -35,18 +35,15 @@ int count_rm_cells, count_rm_wires; void rmunused_module_cells(RTLIL::Module *module, bool verbose) { - SigMap assign_map(module); + SigMap sigmap(module); std::set> queue, unused; SigSet wire2driver; for (auto &it : module->cells_) { RTLIL::Cell *cell = it.second; for (auto &it2 : cell->connections()) { - if (!ct.cell_input(cell->type, it2.first)) { - RTLIL::SigSpec sig = it2.second; - assign_map.apply(sig); - wire2driver.insert(sig, cell); - } + if (!ct.cell_input(cell->type, it2.first)) + wire2driver.insert(sigmap(it2.second), cell); } if (cell->type == "$memwr" || cell->type == "$assert" || cell->has_keep_attr()) queue.insert(cell); @@ -57,15 +54,13 @@ void rmunused_module_cells(RTLIL::Module *module, bool verbose) RTLIL::Wire *wire = it.second; if (wire->port_output || wire->get_bool_attribute("\\keep")) { std::set cell_list; - RTLIL::SigSpec sig = RTLIL::SigSpec(wire); - assign_map.apply(sig); - wire2driver.find(sig, cell_list); + wire2driver.find(sigmap(wire), cell_list); for (auto cell : cell_list) queue.insert(cell); } } - while (queue.size() > 0) + while (!queue.empty()) { std::set> new_queue; for (auto cell : queue) @@ -74,12 +69,10 @@ void rmunused_module_cells(RTLIL::Module *module, bool verbose) for (auto &it : cell->connections()) { if (!ct.cell_output(cell->type, it.first)) { std::set cell_list; - RTLIL::SigSpec sig = it.second; - assign_map.apply(sig); - wire2driver.find(sig, cell_list); - for (auto cell : cell_list) { - if (unused.count(cell) > 0) - new_queue.insert(cell); + wire2driver.find(sigmap(it.second), cell_list); + for (auto c : cell_list) { + if (unused.count(c)) + new_queue.insert(c); } } } From 18cb8b4636933cb5a1ad3040f061d53345d1aa1d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 16 Oct 2014 11:49:31 +0200 Subject: [PATCH 068/492] Don't be too smart with $dff cells with "init" attribute on out signal --- passes/opt/opt_rmdff.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index c7e92ddc1..5f52bb8d8 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -83,7 +83,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx); } - if (dff->type == "$dff" && mux_drivers.has(sig_d)) { + if (dff->type == "$dff" && mux_drivers.has(sig_d) && !has_init) { std::set muxes; mux_drivers.find(sig_d, muxes); for (auto mux : muxes) { From 34caeeb4f3e21d8da3b75682e48ab85c27021b82 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 17 Oct 2014 06:02:38 +0200 Subject: [PATCH 069/492] Fixed a few VS warnings --- kernel/log.h | 2 +- kernel/rtlil.h | 2 +- kernel/satgen.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/log.h b/kernel/log.h index 421c50d3f..10250cb9d 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -181,7 +181,7 @@ struct PerformanceTimer } float sec() const { - return total_ns * 1e-9; + return total_ns * 1e-9f; } #else static int64_t query() { return 0; } diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 5629c8652..8a4d348be 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -898,7 +898,7 @@ struct RTLIL::SigBit SigBit() : wire(NULL), data(RTLIL::State::S0) { } SigBit(RTLIL::State bit) : wire(NULL), data(bit) { } SigBit(RTLIL::Wire *wire) : wire(wire), offset(0) { log_assert(wire && wire->width == 1); } - SigBit(RTLIL::Wire *wire, int offset) : wire(wire), offset(offset) { log_assert(wire); } + SigBit(RTLIL::Wire *wire, int offset) : wire(wire), offset(offset) { log_assert(wire != nullptr); } SigBit(const RTLIL::SigChunk &chunk) : wire(chunk.wire) { log_assert(chunk.width == 1); if (wire) offset = chunk.offset; else data = chunk.data[0]; } SigBit(const RTLIL::SigChunk &chunk, int index) : wire(chunk.wire) { if (wire) offset = chunk.offset + index; else data = chunk.data[index]; } SigBit(const RTLIL::SigSpec &sig); diff --git a/kernel/satgen.h b/kernel/satgen.h index d556f4f32..2c69663c4 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -107,7 +107,7 @@ struct SatGen { log_assert(timestep != 0); std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep)); - return imported_signals[pf].count(bit); + return imported_signals[pf].count(bit) != 0; } void getAsserts(RTLIL::SigSpec &sig_a, RTLIL::SigSpec &sig_en, int timestep = -1) From fda52f05f277720e12aadb4716415ec9bff616a5 Mon Sep 17 00:00:00 2001 From: William Speirs Date: Tue, 14 Oct 2014 17:16:50 -0400 Subject: [PATCH 070/492] Wrapped math in int constructor --- frontends/ast/simplify.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 7e15283c4..70976b68b 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1123,7 +1123,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum); - result_width = abs(left_at_zero_ast->integer - right_at_zero_ast->integer) + 1; + result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; } did_something = true; newNode = new AstNode(AST_CASE, shift_expr); From 31267a1ae8d670c4b8749fc55b07c01d9285a488 Mon Sep 17 00:00:00 2001 From: William Speirs Date: Thu, 16 Oct 2014 12:06:54 -0400 Subject: [PATCH 071/492] Header changes so it will compile on VS --- frontends/verific/verific.cc | 7 +++++-- frontends/vhdl2verilog/vhdl2verilog.cc | 7 +++++-- kernel/driver.cc | 7 +++++-- kernel/yosys.cc | 10 ++++++--- kernel/yosys.h | 29 +++++++++++++++++++++++++- libs/ezsat/ezminisat.cc | 5 ++++- passes/abc/abc.cc | 7 +++++-- passes/cmds/cover.cc | 13 ++++++++++-- passes/cmds/show.cc | 5 ++++- passes/hierarchy/hierarchy.cc | 6 +++++- 10 files changed, 79 insertions(+), 17 deletions(-) diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 5e1894cfd..44dfba0a8 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -20,11 +20,14 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/log.h" -#include #include #include #include -#include + +#ifndef _WIN32 +# include +# include +#endif USING_YOSYS_NAMESPACE diff --git a/frontends/vhdl2verilog/vhdl2verilog.cc b/frontends/vhdl2verilog/vhdl2verilog.cc index 39b4f1496..82ff7b502 100644 --- a/frontends/vhdl2verilog/vhdl2verilog.cc +++ b/frontends/vhdl2verilog/vhdl2verilog.cc @@ -20,14 +20,17 @@ #include "kernel/register.h" #include "kernel/sigtools.h" #include "kernel/log.h" -#include #include #include #include -#include #include #include +#ifndef _WIN32 +# include +# include +#endif + YOSYS_NAMESPACE_BEGIN struct Vhdl2verilogPass : public Pass { diff --git a/kernel/driver.cc b/kernel/driver.cc index 8117a61c5..7f2cdb325 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -27,11 +27,14 @@ #include #include -#include -#include #include #include +#ifndef _WIN32 +# include +#endif + + USING_YOSYS_NAMESPACE int main(int argc, char **argv) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 1ce7b5207..9c1cb58f3 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -33,17 +33,21 @@ #elif defined(__APPLE__) # include #else +# include +# include # include # include #endif -#include #include -#include #include YOSYS_NAMESPACE_BEGIN +#ifdef _WIN32 +const char *yosys_version_str = "Windows"; +#endif + int autoidx = 1; RTLIL::Design *yosys_design = NULL; @@ -325,10 +329,10 @@ void yosys_shutdown() #ifdef YOSYS_ENABLE_PLUGINS for (auto &it : loaded_plugins) dlclose(it.second); -#endif loaded_plugins.clear(); loaded_plugin_aliases.clear(); +#endif } RTLIL::IdString new_id(std::string file, int line, std::string func) diff --git a/kernel/yosys.h b/kernel/yosys.h index 239146d77..e4465edf7 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -68,6 +68,30 @@ # include #endif +// a few platform specific things +#ifdef _WIN32 +# define NOMINMAX +# include +# include // takes care of a number of typedefs +# include +# include + +// these are always a bit dangerous :-) +# define strtok_r strtok_s +# define strdup _strdup +# define snprintf _snprintf +# define access _access +# define getcwd _getcwd +# define mkdir _mkdir +# define popen _popen +# define pclose _pclose + +# define PATH_MAX MAX_PATH +# define F_OK 00 +# define X_OK 00 // note this is NOT correct as there is no execute flag in Windows +#endif + + #define PRIVATE_NAMESPACE_BEGIN namespace { #define PRIVATE_NAMESPACE_END } #define YOSYS_NAMESPACE_BEGIN namespace Yosys { @@ -85,6 +109,9 @@ #if !defined(__GNUC__) && !defined(__clang__) # define __attribute__(...) +# define _NORETURN_ __declspec(noreturn) +#else +# define _NORETURN_ #endif YOSYS_NAMESPACE_BEGIN @@ -96,7 +123,7 @@ namespace RTLIL { struct Cell; } -std::string stringf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +std::string stringf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); std::string vstringf(const char *fmt, va_list ap); std::string next_token(std::string &text, const char *sep); bool patmatch(const char *pattern, const char *string); diff --git a/libs/ezsat/ezminisat.cc b/libs/ezsat/ezminisat.cc index b996d4a3d..dee82a8df 100644 --- a/libs/ezsat/ezminisat.cc +++ b/libs/ezsat/ezminisat.cc @@ -27,7 +27,10 @@ #include #include #include -#include + +#ifndef _WIN32 +# include +#endif #include "../minisat/Solver.h" #include "../minisat/SimpSolver.h" diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 891804393..79aa067d7 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -43,15 +43,18 @@ #include "kernel/sigtools.h" #include "kernel/cost.h" #include "kernel/log.h" -#include #include #include #include -#include #include #include #include +#ifndef _WIN32 +# include +# include +#endif + #include "blifparse.h" USING_YOSYS_NAMESPACE diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc index 857d5aa47..b8baaf3d8 100644 --- a/passes/cmds/cover.cc +++ b/passes/cmds/cover.cc @@ -17,9 +17,18 @@ * */ -#include -#include #include "kernel/yosys.h" +#include + +#ifndef _WIN32 +# include +#else +# include +#endif + +#include "kernel/register.h" +#include "kernel/rtlil.h" +#include "kernel/log.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index c6335cb30..1413742df 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -21,7 +21,10 @@ #include "kernel/celltypes.h" #include "kernel/log.h" #include -#include + +#ifndef _WIN32 +# include +#endif #ifdef YOSYS_ENABLE_READLINE # include diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 4b414d3cb..2a7e96346 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -21,7 +21,11 @@ #include #include #include -#include + +#ifndef _WIN32 +# include +#endif + USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN From 4df902637a3b486ab4836ddc2bde7889c6dccfeb Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 17 Oct 2014 12:04:40 +0200 Subject: [PATCH 072/492] Various MXE build fixes --- kernel/driver.cc | 2 +- kernel/yosys.cc | 21 +++++++++++++++++---- kernel/yosys.h | 11 +++++------ passes/cmds/plugin.cc | 11 +++++++---- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index 7f2cdb325..7a3cd1a1a 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -30,7 +30,7 @@ #include #include -#ifndef _WIN32 +#if !defined(_WIN32) || defined(__MINGW32__) # include #endif diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 9c1cb58f3..ed90a6f33 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -30,6 +30,7 @@ #ifdef _WIN32 # include +# include #elif defined(__APPLE__) # include #else @@ -44,7 +45,7 @@ YOSYS_NAMESPACE_BEGIN -#ifdef _WIN32 +#if defined(_WIN32) && !defined(__MINGW32__) const char *yosys_version_str = "Windows"; #endif @@ -224,7 +225,7 @@ std::string make_temp_file(std::string template_str) x ^= x << 13, x ^= x >> 17, x ^= x << 5; template_str[pos+i] = y[x % y.size()]; } - if (access(template_str.c_str(), F_OK) != 0) + if (_access(template_str.c_str(), 0) != 0) break; } #else @@ -265,6 +266,18 @@ std::string make_temp_dir(std::string template_str) #endif } +#ifdef _WIN32 +bool check_file_exists(std::string filename, bool) +{ + return _access(filename.c_str(), 0); +} +#else +bool check_file_exists(std::string filename, bool is_exec) +{ + return access(filename.c_str(), is_exec ? X_OK : F_OK); +} +#endif + void remove_directory(std::string dirname) { #ifdef _WIN32 @@ -484,10 +497,10 @@ std::string proc_share_dirname() { std::string proc_self_path = proc_self_dirname(); std::string proc_share_path = proc_self_path + "share/"; - if (access(proc_share_path.c_str(), X_OK) == 0) + if (check_file_exists(proc_share_path, true) == 0) return proc_share_path; proc_share_path = proc_self_path + "../share/yosys/"; - if (access(proc_share_path.c_str(), X_OK) == 0) + if (check_file_exists(proc_share_path, true) == 0) return proc_share_path; log_error("proc_share_dirname: unable to determine share/ directory!\n"); } diff --git a/kernel/yosys.h b/kernel/yosys.h index e4465edf7..562cec121 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -70,8 +70,10 @@ // a few platform specific things #ifdef _WIN32 -# define NOMINMAX -# include +# ifndef NOMINMAX +# define NOMINMAX 1 +# endif +# include # include // takes care of a number of typedefs # include # include @@ -80,15 +82,11 @@ # define strtok_r strtok_s # define strdup _strdup # define snprintf _snprintf -# define access _access # define getcwd _getcwd # define mkdir _mkdir # define popen _popen # define pclose _pclose - # define PATH_MAX MAX_PATH -# define F_OK 00 -# define X_OK 00 // note this is NOT correct as there is no execute flag in Windows #endif @@ -130,6 +128,7 @@ bool patmatch(const char *pattern, const char *string); int run_command(const std::string &command, std::function process_line = std::function()); std::string make_temp_file(std::string template_str = "/tmp/yosys_XXXXXX"); std::string make_temp_dir(std::string template_str = "/tmp/yosys_XXXXXX"); +bool check_file(std::string filename, bool is_exec = false); void remove_directory(std::string dirname); template int GetSize(const T &obj) { return obj.size(); } diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc index da597ac45..f7c65bbde 100644 --- a/passes/cmds/plugin.cc +++ b/passes/cmds/plugin.cc @@ -28,9 +28,9 @@ YOSYS_NAMESPACE_BEGIN std::map loaded_plugins; std::map loaded_plugin_aliases; +#ifdef YOSYS_ENABLE_PLUGINS void load_plugin(std::string filename, std::vector aliases) { -#ifdef YOSYS_ENABLE_PLUGINS if (filename.find('/') == std::string::npos) filename = "./" + filename; @@ -44,10 +44,13 @@ void load_plugin(std::string filename, std::vector aliases) for (auto &alias : aliases) loaded_plugin_aliases[alias] = filename; -#else - log_error("This version of yosys is built without plugin support.\n"); -#endif } +#else +void load_plugin(std::string, std::vector) +{ + log_error("This version of yosys is built without plugin support.\n"); +} +#endif struct PluginPass : public Pass { PluginPass() : Pass("plugin", "load and list loaded plugins") { } From 973d37673377c3ddba8020e718e4cd6174379175 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 17 Oct 2014 12:11:15 +0200 Subject: [PATCH 073/492] Added genfiles.zip to MXE "make dist" --- Makefile | 4 +++- passes/techmap/Makefile.inc | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index a43f378e1..2d80c7027 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ INSTALL_SUDO := EXE = OBJS = GENFILES = +EXTRA_OBJS = EXTRA_TARGETS = TARGETS = yosys$(EXE) yosys-config @@ -294,7 +295,7 @@ manual: $(TARGETS) $(EXTRA_TARGETS) clean: rm -rf share cd manual && bash clean.sh - rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) + rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS) rm -f kernel/version_*.o kernel/version_*.cc abc/abc-[0-9a-f]* rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d @@ -323,6 +324,7 @@ ifeq ($(ENABLE_ABC),1) endif echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-$(YOSYS_VER)/readme.txt echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-$(YOSYS_VER)/readme.txt + zip yosys-win32-$(YOSYS_VER)/genfiles.zip $(GENFILES) zip -r yosys-win32-$(YOSYS_VER).zip yosys-win32-$(YOSYS_VER)/ endif diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 9152ff22d..56083ed2b 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -24,7 +24,7 @@ passes/techmap/techmap.inc: techlibs/common/techmap.v passes/techmap/techmap.o: passes/techmap/techmap.inc TARGETS += yosys-filterlib$(EXE) -GENFILES += passes/techmap/filterlib.o +EXTRA_OBJS += passes/techmap/filterlib.o yosys-filterlib$(EXE): passes/techmap/filterlib.o $(P) $(CXX) -o yosys-filterlib$(EXE) $(LDFLAGS) $^ $(LDLIBS) From 468ae923748a01b2763bafa3cf5fba883fe06479 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 17 Oct 2014 14:01:47 +0200 Subject: [PATCH 074/492] Various win32 / vs build fixes --- Makefile | 5 ++++- kernel/log.h | 4 ++-- kernel/rtlil.cc | 2 +- kernel/yosys.cc | 8 ++++---- kernel/yosys.h | 17 +++++++++-------- libs/ezsat/ezsat.h | 1 + passes/cmds/select.cc | 10 +++++----- passes/hierarchy/hierarchy.cc | 4 ++-- 8 files changed, 28 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 2d80c7027..e1c91eaf7 100644 --- a/Makefile +++ b/Makefile @@ -324,8 +324,11 @@ ifeq ($(ENABLE_ABC),1) endif echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-$(YOSYS_VER)/readme.txt echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-$(YOSYS_VER)/readme.txt - zip yosys-win32-$(YOSYS_VER)/genfiles.zip $(GENFILES) + find backends frontends kernel libs passes techlibs -name '*.d' | xargs sed -e 's,^[^ ]*:,,; s, ,\n,g; s, *\\,,;' \ + -e 's,/[^/]*/\.\./,/,g; s,'"$PWD/"',,' | sort -u | sed '/^[^/]/ ! d; s,$,\r,;' > srcfiles.txt + zip yosys-win32-$(YOSYS_VER)/genfiles.zip $(GENFILES) srcfiles.txt zip -r yosys-win32-$(YOSYS_VER).zip yosys-win32-$(YOSYS_VER)/ + rm -f srcfiles.txt endif config-clean: clean diff --git a/kernel/log.h b/kernel/log.h index 10250cb9d..81d01ace7 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -55,8 +55,8 @@ void logv_header(const char *format, va_list ap); void logv_error(const char *format, va_list ap) __attribute__((noreturn)); void log(const char *format, ...) __attribute__((format(printf, 1, 2))); void log_header(const char *format, ...) __attribute__((format(printf, 1, 2))); -void log_error(const char *format, ...) __attribute__((format(printf, 1, 2))) __attribute__((noreturn)); -void log_cmd_error(const char *format, ...) __attribute__((format(printf, 1, 2))) __attribute__((noreturn)); +_NORETURN_ void log_error(const char *format, ...) __attribute__((format(printf, 1, 2))) __attribute__((noreturn)); +_NORETURN_ void log_cmd_error(const char *format, ...) __attribute__((format(printf, 1, 2))) __attribute__((noreturn)); void log_spacer(); void log_push(); diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 5a94008d8..36443c5ac 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2204,7 +2204,7 @@ void RTLIL::SigSpec::unpack() const that->hash_ = 0; } -#define DJB2(_hash, _value) do { (_hash) = (((_hash) << 5) + (_hash)) + (_value); } while (0) +#define DJB2(_hash, _value) (_hash) = (((_hash) << 5) + (_hash)) + (_value) void RTLIL::SigSpec::hash() const { diff --git a/kernel/yosys.cc b/kernel/yosys.cc index ed90a6f33..26665e5b2 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -269,12 +269,12 @@ std::string make_temp_dir(std::string template_str) #ifdef _WIN32 bool check_file_exists(std::string filename, bool) { - return _access(filename.c_str(), 0); + return _access(filename.c_str(), 0) == 0; } #else bool check_file_exists(std::string filename, bool is_exec) { - return access(filename.c_str(), is_exec ? X_OK : F_OK); + return access(filename.c_str(), is_exec ? X_OK : F_OK) == 0; } #endif @@ -497,10 +497,10 @@ std::string proc_share_dirname() { std::string proc_self_path = proc_self_dirname(); std::string proc_share_path = proc_self_path + "share/"; - if (check_file_exists(proc_share_path, true) == 0) + if (check_file_exists(proc_share_path, true)) return proc_share_path; proc_share_path = proc_self_path + "../share/yosys/"; - if (check_file_exists(proc_share_path, true) == 0) + if (check_file_exists(proc_share_path, true)) return proc_share_path; log_error("proc_share_dirname: unable to determine share/ directory!\n"); } diff --git a/kernel/yosys.h b/kernel/yosys.h index 562cec121..a0a42be9b 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -56,6 +56,7 @@ #include #include #include +#include #include #ifndef _YOSYS_ @@ -68,17 +69,18 @@ # include #endif -// a few platform specific things #ifdef _WIN32 -# ifndef NOMINMAX -# define NOMINMAX 1 -# endif +# undef NOMINMAX +# define NOMINMAX 1 +# undef YY_NO_UNISTD_H +# define YY_NO_UNISTD_H 1 +# undef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS 1 + # include -# include // takes care of a number of typedefs # include # include -// these are always a bit dangerous :-) # define strtok_r strtok_s # define strdup _strdup # define snprintf _snprintf @@ -89,7 +91,6 @@ # define PATH_MAX MAX_PATH #endif - #define PRIVATE_NAMESPACE_BEGIN namespace { #define PRIVATE_NAMESPACE_END } #define YOSYS_NAMESPACE_BEGIN namespace Yosys { @@ -128,7 +129,7 @@ bool patmatch(const char *pattern, const char *string); int run_command(const std::string &command, std::function process_line = std::function()); std::string make_temp_file(std::string template_str = "/tmp/yosys_XXXXXX"); std::string make_temp_dir(std::string template_str = "/tmp/yosys_XXXXXX"); -bool check_file(std::string filename, bool is_exec = false); +bool check_file_exists(std::string filename, bool is_exec = false); void remove_directory(std::string dirname); template int GetSize(const T &obj) { return obj.size(); } diff --git a/libs/ezsat/ezsat.h b/libs/ezsat/ezsat.h index cac6ff0f7..5c8c1ed0c 100644 --- a/libs/ezsat/ezsat.h +++ b/libs/ezsat/ezsat.h @@ -25,6 +25,7 @@ #include #include #include +#include class ezSAT { diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index af0df07b3..8e42fe15f 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -1142,7 +1142,7 @@ struct SelectPass : public Pass { if (list_mode || count_mode || !write_file.empty()) { - #define LOG_OBJECT(...) do { if (list_mode) log(__VA_ARGS__); if (f != NULL) fprintf(f, __VA_ARGS__); total_count++; } while (0) + #define LOG_OBJECT(...) { if (list_mode) log(__VA_ARGS__); if (f != NULL) fprintf(f, __VA_ARGS__); total_count++; } int total_count = 0; FILE *f = NULL; if (!write_file.empty()) { @@ -1161,16 +1161,16 @@ struct SelectPass : public Pass { if (sel->selected_module(mod_it.first)) { for (auto &it : mod_it.second->wires_) if (sel->selected_member(mod_it.first, it.first)) - LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)); + LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)) for (auto &it : mod_it.second->memories) if (sel->selected_member(mod_it.first, it.first)) - LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)); + LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)) for (auto &it : mod_it.second->cells_) if (sel->selected_member(mod_it.first, it.first)) - LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)); + LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)) for (auto &it : mod_it.second->processes) if (sel->selected_member(mod_it.first, it.first)) - LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)); + LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first)) } } if (count_mode) diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 2a7e96346..0ea26eb9e 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -174,7 +174,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check for (auto &dir : libdirs) { filename = dir + "/" + RTLIL::unescape_id(cell->type) + ".v"; - if (access(filename.c_str(), F_OK) == 0) { + if (check_file_exists(filename)) { std::vector args; args.push_back(filename); Frontend::frontend_call(design, NULL, filename, "verilog"); @@ -182,7 +182,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check } filename = dir + "/" + RTLIL::unescape_id(cell->type) + ".il"; - if (access(filename.c_str(), F_OK) == 0) { + if (check_file_exists(filename)) { std::vector args; args.push_back(filename); Frontend::frontend_call(design, NULL, filename, "ilang"); From b3a6f8f53019d1984d4e319db459b11da0663aa3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 17 Oct 2014 15:51:33 +0200 Subject: [PATCH 075/492] More win32 (mxe and vs) build fixes --- Makefile | 5 +++-- kernel/driver.cc | 30 ++++++++++++++++++++++++++++++ kernel/yosys.cc | 36 ++++++++++++++++++++++++++++-------- kernel/yosys.h | 11 +++++++---- libs/ezsat/ezsat.cc | 29 ++++++++++++++++++----------- 5 files changed, 86 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index e1c91eaf7..c500e655e 100644 --- a/Makefile +++ b/Makefile @@ -324,8 +324,9 @@ ifeq ($(ENABLE_ABC),1) endif echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-$(YOSYS_VER)/readme.txt echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-$(YOSYS_VER)/readme.txt - find backends frontends kernel libs passes techlibs -name '*.d' | xargs sed -e 's,^[^ ]*:,,; s, ,\n,g; s, *\\,,;' \ - -e 's,/[^/]*/\.\./,/,g; s,'"$PWD/"',,' | sort -u | sed '/^[^/]/ ! d; s,$,\r,;' > srcfiles.txt + find backends frontends kernel libs passes techlibs -name '*.d' | xargs + sed -e 's,^[^ ]*:,,; s, ,\n,g; s, *\\,,; s,/[^/]*/\.\./,/,g; s,'"$$PWD/"',,' $(addsuffix .d,$(basename $(OBJS))) \ + | sort -u | sed '/^[^/]/ ! d; s,$$,\r,;' > srcfiles.txt zip yosys-win32-$(YOSYS_VER)/genfiles.zip $(GENFILES) srcfiles.txt zip -r yosys-win32-$(YOSYS_VER).zip yosys-win32-$(YOSYS_VER)/ rm -f srcfiles.txt diff --git a/kernel/driver.cc b/kernel/driver.cc index 7a3cd1a1a..5e69cced3 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -32,6 +32,36 @@ #if !defined(_WIN32) || defined(__MINGW32__) # include +#else +char *optarg; +int optind = 1, optcur = 1; +int getopt(int argc, char **argv, const char *optstring) +{ + if (optind >= argc || argv[optind][0] != '-') + return -1; + + bool takes_arg = false; + int opt = argv[optind][optcur]; + for (int i = 0; optstring[i]; i++) + if (opt == optstring[i] && optstring[i + 1] == ':') + takes_arg = true; + + if (!takes_arg) { + if (argv[optind][++optcur] == 0) + optind++, optcur = 1; + return opt; + } + + if (argv[optind][++optcur]) { + optarg = argv[optind++] + optcur; + optcur = 1; + return opt; + } + + optarg = argv[++optind]; + optind++, optcur = 1; + return opt; +} #endif diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 26665e5b2..7d1d273cb 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -46,7 +46,7 @@ YOSYS_NAMESPACE_BEGIN #if defined(_WIN32) && !defined(__MINGW32__) -const char *yosys_version_str = "Windows"; +const char *yosys_version_str = "Yosys for Windows (Version Information Unavailable)"; #endif int autoidx = 1; @@ -210,9 +210,19 @@ std::string make_temp_file(std::string template_str) { #ifdef _WIN32 if (template_str.rfind("/tmp/", 0) == 0) { - char path[MAX_PATH+1]; - GetTempPath(MAX_PATH+1, path); - template_str = stringf("%s\\%s", path, template_str.c_str() + 5); +# ifdef __MINGW32__ + char longpath[MAX_PATH + 1]; + char shortpath[MAX_PATH + 1]; +# else + WCHAR longpath[MAX_PATH + 1]; + TCHAR shortpath[MAX_PATH + 1]; +# endif + if (!GetTempPath(MAX_PATH+1, longpath)) + log_error("GetTempPath() failed.\n"); + if (!GetShortPathName(longpath, shortpath, MAX_PATH + 1)) + log_error("GetShortPathName() failed.\n"); + log_assert(sizeof(TCHAR) == sizeof(char)); + template_str = stringf("%s\\%s", shortpath, template_str.c_str() + 5); } size_t pos = template_str.rfind("XXXXXX"); @@ -475,14 +485,24 @@ std::string proc_self_dirname() #elif defined(_WIN32) std::string proc_self_dirname() { - char longpath[MAX_PATH+1], shortpath[MAX_PATH+1]; + int i = 0; +# ifdef __MINGW32__ + char longpath[MAX_PATH + 1]; + char shortpath[MAX_PATH + 1]; +# else + WCHAR longpath[MAX_PATH + 1]; + TCHAR shortpath[MAX_PATH + 1]; +# endif if (!GetModuleFileName(0, longpath, MAX_PATH+1)) log_error("GetModuleFileName() failed.\n"); if (!GetShortPathName(longpath, shortpath, MAX_PATH+1)) log_error("GetShortPathName() failed.\n"); - for (int i = strlen(shortpath)-1; i >= 0 && shortpath[i] != '/' && shortpath[i] != '\\' ; i--) - shortpath[i] = 0; - return std::string(shortpath); + while (shortpath[i] != 0) + i++; + while (i > 0 && shortpath[i-1] != '/' && shortpath[i-1] != '\\') + shortpath[--i] = 0; + log_assert(sizeof(TCHAR) == sizeof(char)); + return std::string((char*)shortpath); } #elif defined(EMSCRIPTEN) std::string proc_self_dirname() diff --git a/kernel/yosys.h b/kernel/yosys.h index a0a42be9b..b9182c1df 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -60,9 +60,9 @@ #include #ifndef _YOSYS_ -# error It looks like you are trying to build Yosys with the config defines set. \ +# error It looks like you are trying to build Yosys without the config defines set. \ When building Yosys with a custom make system, make sure you set all the \ - defines the Yosys Makefile would set for your build configuration. + defines the Yosys Makefile would set for your build configuration. #endif #ifdef YOSYS_ENABLE_TCL @@ -74,8 +74,6 @@ # define NOMINMAX 1 # undef YY_NO_UNISTD_H # define YY_NO_UNISTD_H 1 -# undef _CRT_SECURE_NO_WARNINGS -# define _CRT_SECURE_NO_WARNINGS 1 # include # include @@ -89,6 +87,11 @@ # define popen _popen # define pclose _pclose # define PATH_MAX MAX_PATH + +# ifndef __MINGW32__ +# define isatty _isatty +# define fileno _fileno +# endif #endif #define PRIVATE_NAMESPACE_BEGIN namespace { diff --git a/libs/ezsat/ezsat.cc b/libs/ezsat/ezsat.cc index 54a6e9c71..657bed9d2 100644 --- a/libs/ezsat/ezsat.cc +++ b/libs/ezsat/ezsat.cc @@ -22,12 +22,24 @@ #include #include #include +#include #include const int ezSAT::CONST_TRUE = 1; const int ezSAT::CONST_FALSE = 2; +static std::string my_int_to_string(int i) +{ +#ifdef __MINGW32__ + char buffer[64]; + snprintf(buffer, 64, "%d", i); + return buffer; +#else + return std::to_string(i); +#endif +} + ezSAT::ezSAT() { flag_keep_cnf = false; @@ -183,7 +195,7 @@ int ezSAT::expression(OpId op, const std::vector &args) if (expressionsCache.count(myExpr) > 0) { id = expressionsCache.at(myExpr); } else { - id = -(expressions.size() + 1); + id = -(int(expressions.size()) + 1); expressionsCache[myExpr] = id; expressions.push_back(myExpr); } @@ -490,13 +502,13 @@ int ezSAT::bound(int id) const std::string ezSAT::cnfLiteralInfo(int idx) const { - for (size_t i = 0; i < cnfLiteralVariables.size(); i++) { + for (int i = 0; i < int(cnfLiteralVariables.size()); i++) { if (cnfLiteralVariables[i] == idx) return to_string(i+1); if (cnfLiteralVariables[i] == -idx) return "NOT " + to_string(i+1); } - for (size_t i = 0; i < cnfExpressionVariables.size(); i++) { + for (int i = 0; i < int(cnfExpressionVariables.size()); i++) { if (cnfExpressionVariables[i] == idx) return to_string(-i-1); if (cnfExpressionVariables[i] == -idx) @@ -670,9 +682,7 @@ std::vector ezSAT::vec_var(std::string name, int numBits) { std::vector vec; for (int i = 0; i < numBits; i++) { - char buf[64]; - snprintf(buf, 64, " [%d]", i); - vec.push_back(VAR(name + buf)); + vec.push_back(VAR(name + my_int_to_string(i))); } return vec; } @@ -1245,11 +1255,8 @@ static std::string expression2str(const std::pair> #undef X } text += ":"; - for (auto it : data.second) { - char buf[64]; - snprintf(buf, 64, " %d", it); - text += buf; - } + for (auto it : data.second) + text += " " + my_int_to_string(it); return text; } From e8a609f0e52b14d39598bae81910e8c80ac5ef7c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 17 Oct 2014 16:00:28 +0200 Subject: [PATCH 076/492] Added vcxproj_files.txt to MXE "make dist" --- Makefile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index c500e655e..5fa871d49 100644 --- a/Makefile +++ b/Makefile @@ -324,12 +324,14 @@ ifeq ($(ENABLE_ABC),1) endif echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-$(YOSYS_VER)/readme.txt echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-$(YOSYS_VER)/readme.txt - find backends frontends kernel libs passes techlibs -name '*.d' | xargs - sed -e 's,^[^ ]*:,,; s, ,\n,g; s, *\\,,; s,/[^/]*/\.\./,/,g; s,'"$$PWD/"',,' $(addsuffix .d,$(basename $(OBJS))) \ - | sort -u | sed '/^[^/]/ ! d; s,$$,\r,;' > srcfiles.txt - zip yosys-win32-$(YOSYS_VER)/genfiles.zip $(GENFILES) srcfiles.txt + sed -e 's,^[^ ]*:,,; s, ,\n,g; s, *\\,,; s,/[^/]*/\.\./,/,g; s,'"$$PWD/"',,' \ + $(addsuffix .d,$(basename $(OBJS))) | sort -u | grep '^[^/]' > srcfiles.txt + { egrep '\.(h|hh|hpp|inc)$$' srcfiles.txt | sed 's,.*,,'; echo; \ + egrep -v '\.(h|hh|hpp|inc)$$' srcfiles.txt | sed 's,.*,,'; } > vcxproj_files.txt + sed -i 's/$$/\r/' srcfiles.txt vcxproj_files.txt + zip yosys-win32-$(YOSYS_VER)/genfiles.zip $(GENFILES) srcfiles.txt vcxproj_files.txt zip -r yosys-win32-$(YOSYS_VER).zip yosys-win32-$(YOSYS_VER)/ - rm -f srcfiles.txt + rm -f srcfiles.txt vcxproj_files.txt endif config-clean: clean From c321b419d45be8c25bac671df776a779da78b090 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 17 Oct 2014 16:39:24 +0200 Subject: [PATCH 077/492] Added notes regarding building in VS --- CodingReadme | 35 +++++++++++++++++++++++++++++++++++ Makefile | 6 +++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/CodingReadme b/CodingReadme index 2404a7a5a..8bcbe6125 100644 --- a/CodingReadme +++ b/CodingReadme @@ -67,6 +67,41 @@ of "foobar.size()". (GetSize() is defined by kernel/yosys.h) Use range-based for loops whenever applicable. +Building in Visual Studio +========================= + +1. Create an empty Visual C++ Win32 Console App project + (recommended name: YosysVS) + +2. Close VS and launch "Git Bash" in the project directory + +3. Prepare sources + + git clone https://github.com/cliffordwolf/yosys.git yosys + cd yosys + + curl -O http://www.clifford.at/yosys/nogit/yosys-win32-.zip + unzip yosys-win32-.zip + unzip yosys-win32-/genfiles.zip + +4. Add files to VS project + + notepad vcxproj_files.txt + notepad ../YosysVS/YosysVS.vcxproj + + (replace the empty in YosysVS.vcxproj + with the XML text from vcxproj_files.txt) + +5. Open project in VS and go to the project properties: + + C/C++ -> General -> Additional Include Directories + Add: ..\yosys + + C/C++ -> Preprocessor -> Preprocessor Definitions + Add: _YOSYS_;_CRT_SECURE_NO_WARNINGS + +6. Build YosysVS + Checklist for adding internal cell types ======================================== diff --git a/Makefile b/Makefile index 5fa871d49..75af44659 100644 --- a/Makefile +++ b/Makefile @@ -325,9 +325,9 @@ endif echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-$(YOSYS_VER)/readme.txt echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-$(YOSYS_VER)/readme.txt sed -e 's,^[^ ]*:,,; s, ,\n,g; s, *\\,,; s,/[^/]*/\.\./,/,g; s,'"$$PWD/"',,' \ - $(addsuffix .d,$(basename $(OBJS))) | sort -u | grep '^[^/]' > srcfiles.txt - { egrep '\.(h|hh|hpp|inc)$$' srcfiles.txt | sed 's,.*,,'; echo; \ - egrep -v '\.(h|hh|hpp|inc)$$' srcfiles.txt | sed 's,.*,,'; } > vcxproj_files.txt + $(addsuffix .d,$(basename $(OBJS))) | sort -u | grep '^[^/]' | grep -v kernel/version_ > srcfiles.txt + { echo ''; egrep '\.(h|hh|hpp|inc)$$' srcfiles.txt | sed 's,.*,,'; \ + egrep -v '\.(h|hh|hpp|inc)$$' srcfiles.txt | sed 's,.*,,'; echo ''; } > vcxproj_files.txt sed -i 's/$$/\r/' srcfiles.txt vcxproj_files.txt zip yosys-win32-$(YOSYS_VER)/genfiles.zip $(GENFILES) srcfiles.txt vcxproj_files.txt zip -r yosys-win32-$(YOSYS_VER).zip yosys-win32-$(YOSYS_VER)/ From b5da3a60e101a26dbcbd6a8565343c281ba464f8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 18 Oct 2014 14:15:05 +0200 Subject: [PATCH 078/492] Moved yosys-config.in to misc/ --- Makefile | 4 ++-- yosys-config.in => misc/yosys-config.in | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename yosys-config.in => misc/yosys-config.in (100%) diff --git a/Makefile b/Makefile index 75af44659..c2d1ac0b2 100644 --- a/Makefile +++ b/Makefile @@ -224,9 +224,9 @@ kernel/version_$(GIT_REV).cc: Makefile $(Q) echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys $(YOSYS_VER) (git sha1 $(GIT_REV), $(notdir $(CXX)) ` \ $(CXX) --version | tr ' ()' '\n' | grep '^[0-9]' | head -n1` $(filter -f% -m% -O% -DNDEBUG,$(CXXFLAGS)))\"; }" > kernel/version_$(GIT_REV).cc -yosys-config: yosys-config.in +yosys-config: misc/yosys-config.in $(P) $(SED) -e 's,@CXX@,$(CXX),;' -e 's,@CXXFLAGS@,$(CXXFLAGS),;' -e 's,@LDFLAGS@,$(LDFLAGS),;' -e 's,@LDLIBS@,$(LDLIBS),;' \ - -e 's,@BINDIR@,$(DESTDIR)/bin,;' -e 's,@DATDIR@,$(DESTDIR)/share/yosys,;' < yosys-config.in > yosys-config + -e 's,@BINDIR@,$(DESTDIR)/bin,;' -e 's,@DATDIR@,$(DESTDIR)/share/yosys,;' < misc/yosys-config.in > yosys-config $(Q) chmod +x yosys-config abc/abc-$(ABCREV)$(EXE): diff --git a/yosys-config.in b/misc/yosys-config.in similarity index 100% rename from yosys-config.in rename to misc/yosys-config.in From 85572b05e5359f28c1625b873dc14428f796a454 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 18 Oct 2014 15:17:33 +0200 Subject: [PATCH 079/492] Create vcxsrc in mxe build "make dist" --- .gitignore | 2 ++ CodingReadme | 46 ++++++++++++++++++++++++------------------- Makefile | 24 +++++++++++----------- misc/create_vcxsrc.sh | 39 ++++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 33 deletions(-) create mode 100644 misc/create_vcxsrc.sh diff --git a/.gitignore b/.gitignore index 557240f0f..5d470732f 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ /yosys-filterlib.html /kernel/version_*.cc /share +/yosys-win32-mxebin-* +/yosys-win32-vcxsrc-* diff --git a/CodingReadme b/CodingReadme index 8bcbe6125..0e3ff6949 100644 --- a/CodingReadme +++ b/CodingReadme @@ -67,32 +67,27 @@ of "foobar.size()". (GetSize() is defined by kernel/yosys.h) Use range-based for loops whenever applicable. -Building in Visual Studio -========================= + +Creating the Visual Studio Template Project +=========================================== 1. Create an empty Visual C++ Win32 Console App project - (recommended name: YosysVS) -2. Close VS and launch "Git Bash" in the project directory + Microsoft Visual Studio Express 2013 for Windows Desktop + Open New Project Wizard (File -> New Project..) -3. Prepare sources + Project Name: YosysVS + Solution Name: YosysVS + [X] Create directory for solution + [ ] Add to source control - git clone https://github.com/cliffordwolf/yosys.git yosys - cd yosys + [X] Console applications + [X] Empty Projcect + [ ] SDL checks - curl -O http://www.clifford.at/yosys/nogit/yosys-win32-.zip - unzip yosys-win32-.zip - unzip yosys-win32-/genfiles.zip +2. Open YosysVS Project Properties -4. Add files to VS project - - notepad vcxproj_files.txt - notepad ../YosysVS/YosysVS.vcxproj - - (replace the empty in YosysVS.vcxproj - with the XML text from vcxproj_files.txt) - -5. Open project in VS and go to the project properties: + Select Configuration: All Configurations C/C++ -> General -> Additional Include Directories Add: ..\yosys @@ -100,7 +95,18 @@ Building in Visual Studio C/C++ -> Preprocessor -> Preprocessor Definitions Add: _YOSYS_;_CRT_SECURE_NO_WARNINGS -6. Build YosysVS +3. Resulting file system tree: + + YosysVS/ + YosysVS/YosysVS + YosysVS/YosysVS/YosysVS.vcxproj + YosysVS/YosysVS/YosysVS.vcxproj.filters + YosysVS/YosysVS.sdf + YosysVS/YosysVS.sln + YosysVS/YosysVS.v12.suo + +4. Zip YosysVS as YosysVS-Tpl-v1.zip + Checklist for adding internal cell types diff --git a/Makefile b/Makefile index c2d1ac0b2..1819e6c3d 100644 --- a/Makefile +++ b/Makefile @@ -315,23 +315,21 @@ qtcreator: ifeq ($(CONFIG),mxe) dist: $(TARGETS) $(EXTRA_TARGETS) - rm -rf yosys-win32-$(YOSYS_VER) - rm -rf yosys-win32-$(YOSYS_VER).zip - mkdir -p yosys-win32-$(YOSYS_VER) - cp -r yosys.exe share/ yosys-win32-$(YOSYS_VER)/ + rm -rf yosys-win32-{mxebin,vcxsrc}-$(YOSYS_VER){,.zip} + mkdir -p yosys-win32-mxebin-$(YOSYS_VER) + cp -r yosys.exe share/ yosys-win32-mxebin-$(YOSYS_VER)/ ifeq ($(ENABLE_ABC),1) - cp -r yosys-abc.exe abc/lib/x86/pthreadVC2.dll yosys-win32-$(YOSYS_VER)/ + cp -r yosys-abc.exe abc/lib/x86/pthreadVC2.dll yosys-win32-mxebin-$(YOSYS_VER)/ endif - echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-$(YOSYS_VER)/readme.txt - echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-$(YOSYS_VER)/readme.txt + echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-mxebin-$(YOSYS_VER)/readme.txt + echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-mxebin-$(YOSYS_VER)/readme.txt sed -e 's,^[^ ]*:,,; s, ,\n,g; s, *\\,,; s,/[^/]*/\.\./,/,g; s,'"$$PWD/"',,' \ $(addsuffix .d,$(basename $(OBJS))) | sort -u | grep '^[^/]' | grep -v kernel/version_ > srcfiles.txt - { echo ''; egrep '\.(h|hh|hpp|inc)$$' srcfiles.txt | sed 's,.*,,'; \ - egrep -v '\.(h|hh|hpp|inc)$$' srcfiles.txt | sed 's,.*,,'; echo ''; } > vcxproj_files.txt - sed -i 's/$$/\r/' srcfiles.txt vcxproj_files.txt - zip yosys-win32-$(YOSYS_VER)/genfiles.zip $(GENFILES) srcfiles.txt vcxproj_files.txt - zip -r yosys-win32-$(YOSYS_VER).zip yosys-win32-$(YOSYS_VER)/ - rm -f srcfiles.txt vcxproj_files.txt + bash misc/create_vcxsrc.sh yosys-win32-vcxsrc-$(YOSYS_VER) + zip yosys-win32-vcxsrc-$(YOSYS_VER)/genfiles.zip $(GENFILES) + zip -r yosys-win32-mxebin-$(YOSYS_VER).zip yosys-win32-mxebin-$(YOSYS_VER)/ + zip -r yosys-win32-vcxsrc-$(YOSYS_VER).zip yosys-win32-vcxsrc-$(YOSYS_VER)/ + rm -f srcfiles.txt endif config-clean: clean diff --git a/misc/create_vcxsrc.sh b/misc/create_vcxsrc.sh new file mode 100644 index 000000000..eb2239303 --- /dev/null +++ b/misc/create_vcxsrc.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +set -ex +vcxsrc="$1" + +rm -rf YosysVS-Tpl-v1.zip YosysVS +wget http://www.clifford.at/yosys/nogit/YosysVS-Tpl-v1.zip + +unzip YosysVS-Tpl-v1.zip +rm -f YosysVS-Tpl-v1.zip +mv YosysVS "$vcxsrc" + +{ + n=$(grep -B999 '' "$vcxsrc"/YosysVS/YosysVS.vcxproj | wc -l) + head -n$n "$vcxsrc"/YosysVS/YosysVS.vcxproj + egrep '\.(h|hh|hpp|inc)$' srcfiles.txt | sed 's,.*,,' + egrep -v '\.(h|hh|hpp|inc)$' srcfiles.txt | sed 's,.*,,' + tail -n +$((n+1)) "$vcxsrc"/YosysVS/YosysVS.vcxproj +} > "$vcxsrc"/YosysVS/YosysVS.vcxproj.new + +mv "$vcxsrc"/YosysVS/YosysVS.vcxproj.new "$vcxsrc"/YosysVS/YosysVS.vcxproj + +mkdir -p "$vcxsrc"/yosys +tar -cf - -T srcfiles.txt | tar -xf - -C "$vcxsrc"/yosys + +cat > "$vcxsrc"/readme-git.txt << EOT +Using a git working copy for the yosys source code: + +Open "Git Bash" in this directory and run: + + mv yosys yosys.bak + git clone https://github.com/cliffordwolf/yosys.git yosys + cd yosys + git checkout -B master $(git rev-parse HEAD | cut -c1-10) + unzip ../genfiles.zip +EOT + +sed -i 's/$/\r/; s/\r\r*/\r/g;' "$vcxsrc"/YosysVS/YosysVS.vcxproj "$vcxsrc"/readme-git.txt + From 84ffe04075bbddfd1b288295c07d036416923c3a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 18 Oct 2014 15:20:38 +0200 Subject: [PATCH 080/492] Fixed various VS warnings --- frontends/ast/simplify.cc | 2 +- kernel/log.cc | 2 +- kernel/rtlil.cc | 4 ++-- kernel/yosys.cc | 2 +- libs/ezsat/ezsat.cc | 4 ++-- passes/opt/opt_clean.cc | 2 +- passes/opt/share.cc | 4 ++-- passes/techmap/dfflibmap.cc | 8 ++++---- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 70976b68b..e2d63de60 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2457,7 +2457,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) } log_assert(block != NULL); - log_assert(variables.count(str)); + log_assert(variables.count(str) != 0); while (!block->children.empty()) { diff --git a/kernel/log.cc b/kernel/log.cc index 19eb38c73..807f58bf6 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -64,7 +64,7 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) counter.QuadPart *= 1000000; counter.QuadPart /= freq.QuadPart; - tv->tv_sec = counter.QuadPart / 1000000; + tv->tv_sec = long(counter.QuadPart / 1000000); tv->tv_usec = counter.QuadPart % 1000000; return 0; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 36443c5ac..1a9eb4d14 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1778,7 +1778,7 @@ const std::map &RTLIL::Cell::connections() cons bool RTLIL::Cell::hasParam(RTLIL::IdString paramname) const { - return parameters.count(paramname); + return parameters.count(paramname) != 0; } void RTLIL::Cell::unsetParam(RTLIL::IdString paramname) @@ -3041,7 +3041,7 @@ bool RTLIL::SigSpec::parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, R if (lhs.chunks_.size() == 1) { char *p = (char*)str.c_str(), *endptr; - long long int val = strtoll(p, &endptr, 10); + long int val = strtol(p, &endptr, 10); if (endptr && endptr != p && *endptr == 0) { sig = RTLIL::SigSpec(val, lhs.width_); cover("kernel.rtlil.sigspec.parse.rhs_dec"); diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 7d1d273cb..f314f546a 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -231,7 +231,7 @@ std::string make_temp_file(std::string template_str) while (1) { for (int i = 0; i < 6; i++) { static std::string y = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - static uint32_t x = 314159265 ^ time(NULL); + static uint32_t x = 314159265 ^ uint32_t(time(NULL)); x ^= x << 13, x ^= x >> 17, x ^= x << 5; template_str[pos+i] = y[x % y.size()]; } diff --git a/libs/ezsat/ezsat.cc b/libs/ezsat/ezsat.cc index 657bed9d2..b713c4c91 100644 --- a/libs/ezsat/ezsat.cc +++ b/libs/ezsat/ezsat.cc @@ -1118,7 +1118,7 @@ int64_t ezSAT::vec_model_get_signed(const std::vector &modelExpressions, co for (int i = 0; i < 64; i++) { int j = i < int(vec1.size()) ? i : vec1.size()-1; if (modelMap.at(vec1[j])) - value |= 1 << i; + value |= int64_t(1) << i; } return value; } @@ -1132,7 +1132,7 @@ uint64_t ezSAT::vec_model_get_unsigned(const std::vector &modelExpressions, modelMap[modelExpressions[i]] = modelValues[i]; for (int i = 0; i < int(vec1.size()); i++) if (modelMap.at(vec1[i])) - value |= 1 << i; + value |= uint64_t(1) << i; return value; } diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 4194f88c3..8a20898cf 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -112,7 +112,7 @@ bool compare_signals(RTLIL::SigBit &s1, RTLIL::SigBit &s2, SigPool ®s, SigPoo if (regs.check_any(s1) != regs.check_any(s2)) return regs.check_any(s2); if (direct_wires.count(w1) != direct_wires.count(w2)) - return direct_wires.count(w2); + return direct_wires.count(w2) != 0; if (conns.check_any(s1) != conns.check_any(s2)) return conns.check_any(s2); } diff --git a/passes/opt/share.cc b/passes/opt/share.cc index 354586937..2496f15d3 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -747,7 +747,7 @@ struct ShareWorker forbidden_controls_cache[cell].insert(bits.begin(), bits.end()); } - log_assert(recursion_state.count(cell)); + log_assert(recursion_state.count(cell) != 0); recursion_state.erase(cell); return forbidden_controls_cache[cell]; @@ -862,7 +862,7 @@ struct ShareWorker activation_patterns_cache[cell].insert(c_patterns.begin(), c_patterns.end()); } - log_assert(recursion_state.count(cell)); + log_assert(recursion_state.count(cell) != 0); recursion_state.erase(cell); optimize_activation_patterns(activation_patterns_cache[cell]); diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index 510dcd60b..a02eafb96 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -108,7 +108,7 @@ static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool LibertyAst *best_cell = NULL; std::map best_cell_ports; int best_cell_pins = 0; - float best_cell_area = 0; + double best_cell_area = 0; if (ast->id != "library") log_error("Format error in liberty file.\n"); @@ -144,7 +144,7 @@ static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool this_cell_ports[cell_rst_pin] = 'R'; this_cell_ports[cell_next_pin] = 'D'; - float area = 0; + double area = 0; LibertyAst *ar = cell->find("area"); if (ar != NULL && !ar->value.empty()) area = atof(ar->value.c_str()); @@ -204,7 +204,7 @@ static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bo LibertyAst *best_cell = NULL; std::map best_cell_ports; int best_cell_pins = 0; - float best_cell_area = 0; + double best_cell_area = 0; if (ast->id != "library") log_error("Format error in liberty file.\n"); @@ -236,7 +236,7 @@ static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bo this_cell_ports[cell_clr_pin] = 'R'; this_cell_ports[cell_next_pin] = 'D'; - float area = 0; + double area = 0; LibertyAst *ar = cell->find("area"); if (ar != NULL && !ar->value.empty()) area = atof(ar->value.c_str()); From 6bcb4f1f45d1310718d356b7e439bd87fc7d045a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 18 Oct 2014 16:51:50 +0100 Subject: [PATCH 081/492] Fixed shell prompt and proc_self_dirname() for win32 --- kernel/yosys.cc | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index f314f546a..2303673c5 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -221,8 +221,10 @@ std::string make_temp_file(std::string template_str) log_error("GetTempPath() failed.\n"); if (!GetShortPathName(longpath, shortpath, MAX_PATH + 1)) log_error("GetShortPathName() failed.\n"); - log_assert(sizeof(TCHAR) == sizeof(char)); - template_str = stringf("%s\\%s", shortpath, template_str.c_str() + 5); + std::string path; + for (int i = 0; shortpath[i]; i++) + path += char(shortpath[i]); + template_str = stringf("%s\\%s", path.c_str(), template_str.c_str() + 5); } size_t pos = template_str.rfind("XXXXXX"); @@ -501,8 +503,10 @@ std::string proc_self_dirname() i++; while (i > 0 && shortpath[i-1] != '/' && shortpath[i-1] != '\\') shortpath[--i] = 0; - log_assert(sizeof(TCHAR) == sizeof(char)); - return std::string((char*)shortpath); + std::string path; + for (i = 0; shortpath[i]; i++) + path += char(shortpath[i]); + return path; } #elif defined(EMSCRIPTEN) std::string proc_self_dirname() @@ -516,12 +520,21 @@ std::string proc_self_dirname() std::string proc_share_dirname() { std::string proc_self_path = proc_self_dirname(); +#ifdef _WIN32 + std::string proc_share_path = proc_self_path + "share\\"; + if (check_file_exists(proc_share_path, true)) + return proc_share_path; + proc_share_path = proc_self_path + "..\\share\\"; + if (check_file_exists(proc_share_path, true)) + return proc_share_path; +#else std::string proc_share_path = proc_self_path + "share/"; if (check_file_exists(proc_share_path, true)) return proc_share_path; proc_share_path = proc_self_path + "../share/yosys/"; if (check_file_exists(proc_share_path, true)) return proc_share_path; +#endif log_error("proc_share_dirname: unable to determine share/ directory!\n"); } @@ -789,11 +802,16 @@ void shell(RTLIL::Design *design) char *command = NULL; #ifdef YOSYS_ENABLE_READLINE while ((command = readline(create_prompt(design, recursion_counter))) != NULL) + { #else char command_buffer[4096]; - while ((command = fgets(command_buffer, 4096, stdin)) != NULL) -#endif + while (1) { + fputs(create_prompt(design, recursion_counter), stdout); + fflush(stdout); + if ((command = fgets(command_buffer, 4096, stdin)) == NULL) + break; +#endif if (command[strspn(command, " \t\r\n")] == 0) continue; #ifdef YOSYS_ENABLE_READLINE From 41db98ba3113b45220ad5300c51e608f89c1d263 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 18 Oct 2014 16:52:06 +0100 Subject: [PATCH 082/492] Fixed typo in test_cell --- passes/tests/test_cell.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index 03fb31d28..3406d7e3e 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -522,7 +522,7 @@ struct TestCellPass : public Pass { log(" -map {filename}\n"); log(" pass this option to techmap.\n"); log("\n"); - log(" -simplib\n"); + log(" -simlib\n"); log(" use \"techmap -map +/simlib.v -max_iter 2 -autoproc\"\n"); log("\n"); log(" -script {script_file}\n"); From 57cd48523694205141ac6169da7a918e5b8d9972 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 18 Oct 2014 18:21:33 +0200 Subject: [PATCH 083/492] Disabled READLINE in MXE cross build --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 1819e6c3d..f5f6c2f9a 100644 --- a/Makefile +++ b/Makefile @@ -355,6 +355,7 @@ config-mxe: clean echo 'CONFIG := mxe' > Makefile.conf echo 'ENABLE_TCL := 0' >> Makefile.conf echo 'ENABLE_PLUGINS := 0' >> Makefile.conf + echo 'ENABLE_READLINE := 0' >> Makefile.conf config-gprof: clean echo 'CONFIG := gcc' > Makefile.conf From 0471d158d955804c011338c5c664dfa7a38aed1f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 18 Oct 2014 19:00:52 +0200 Subject: [PATCH 084/492] Various improvements to version reporting on win32 --- Makefile | 7 ++++--- kernel/yosys.cc | 4 ---- misc/create_vcxsrc.sh | 23 +++++++++++++++++++---- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index f5f6c2f9a..f3f304ce1 100644 --- a/Makefile +++ b/Makefile @@ -325,11 +325,12 @@ endif echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-mxebin-$(YOSYS_VER)/readme.txt sed -e 's,^[^ ]*:,,; s, ,\n,g; s, *\\,,; s,/[^/]*/\.\./,/,g; s,'"$$PWD/"',,' \ $(addsuffix .d,$(basename $(OBJS))) | sort -u | grep '^[^/]' | grep -v kernel/version_ > srcfiles.txt - bash misc/create_vcxsrc.sh yosys-win32-vcxsrc-$(YOSYS_VER) - zip yosys-win32-vcxsrc-$(YOSYS_VER)/genfiles.zip $(GENFILES) + bash misc/create_vcxsrc.sh yosys-win32-vcxsrc $(YOSYS_VER) $(GIT_REV) + echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys (Version Information Unavailable)\"; }" > kernel/version.cc + zip yosys-win32-vcxsrc-$(YOSYS_VER)/genfiles.zip $(GENFILES) kernel/version.cc zip -r yosys-win32-mxebin-$(YOSYS_VER).zip yosys-win32-mxebin-$(YOSYS_VER)/ zip -r yosys-win32-vcxsrc-$(YOSYS_VER).zip yosys-win32-vcxsrc-$(YOSYS_VER)/ - rm -f srcfiles.txt + rm -f srcfiles.txt kernel/version.cc endif config-clean: clean diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 2303673c5..e26eaf4be 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -45,10 +45,6 @@ YOSYS_NAMESPACE_BEGIN -#if defined(_WIN32) && !defined(__MINGW32__) -const char *yosys_version_str = "Yosys for Windows (Version Information Unavailable)"; -#endif - int autoidx = 1; RTLIL::Design *yosys_design = NULL; diff --git a/misc/create_vcxsrc.sh b/misc/create_vcxsrc.sh index eb2239303..215e27c53 100644 --- a/misc/create_vcxsrc.sh +++ b/misc/create_vcxsrc.sh @@ -1,7 +1,9 @@ #!/bin/bash set -ex -vcxsrc="$1" +vcxsrc="$1-$2" +yosysver="$2" +gitsha="$3" rm -rf YosysVS-Tpl-v1.zip YosysVS wget http://www.clifford.at/yosys/nogit/YosysVS-Tpl-v1.zip @@ -15,6 +17,7 @@ mv YosysVS "$vcxsrc" head -n$n "$vcxsrc"/YosysVS/YosysVS.vcxproj egrep '\.(h|hh|hpp|inc)$' srcfiles.txt | sed 's,.*,,' egrep -v '\.(h|hh|hpp|inc)$' srcfiles.txt | sed 's,.*,,' + echo '' tail -n +$((n+1)) "$vcxsrc"/YosysVS/YosysVS.vcxproj } > "$vcxsrc"/YosysVS/YosysVS.vcxproj.new @@ -22,10 +25,13 @@ mv "$vcxsrc"/YosysVS/YosysVS.vcxproj.new "$vcxsrc"/YosysVS/YosysVS.vcxproj mkdir -p "$vcxsrc"/yosys tar -cf - -T srcfiles.txt | tar -xf - -C "$vcxsrc"/yosys +cp -r share "$vcxsrc"/ + +echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys" \ + "$yosysver (git sha1 $gitsha, Visual Studio)\"; }" > "$vcxsrc"/yosys/kernel/version.cc cat > "$vcxsrc"/readme-git.txt << EOT -Using a git working copy for the yosys source code: - +Want to use a git working copy for the yosys source code? Open "Git Bash" in this directory and run: mv yosys yosys.bak @@ -35,5 +41,14 @@ Open "Git Bash" in this directory and run: unzip ../genfiles.zip EOT -sed -i 's/$/\r/; s/\r\r*/\r/g;' "$vcxsrc"/YosysVS/YosysVS.vcxproj "$vcxsrc"/readme-git.txt +cat > "$vcxsrc"/readme-abc.txt << EOT +Yosys is using "ABC" for gate-level optimizations and technology +mapping. Download yosys-win32-mxebin-$yosysver.zip and copy the +following files from it into this directory: + + pthreadVC2.dll + yosys-abc.exe +EOT + +sed -i 's/$/\r/; s/\r\r*/\r/g;' "$vcxsrc"/YosysVS/YosysVS.vcxproj "$vcxsrc"/readme-git.txt "$vcxsrc"/readme-abc.txt From bb631c6f5c0026b0920996205329dae5836f9a1b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 18 Oct 2014 19:01:44 +0200 Subject: [PATCH 085/492] Also look for yosys-abc in parent dir on win32 --- passes/abc/abc.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 79aa067d7..9d6d94579 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -1106,6 +1106,11 @@ struct AbcPass : public Pass { bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; int lut_mode = 0; +#ifdef _WIN32 + if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe")) + exe_file = proc_self_dirname() + "..\\yosys-abc"; +#endif + size_t argidx; char pwd [PATH_MAX]; if (!getcwd(pwd, sizeof(pwd))) { From 6c1c1e9a07c66b37f65835ed03370ac062616b7a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 18 Oct 2014 19:26:03 +0200 Subject: [PATCH 086/492] Improved new_id() for win32 --- kernel/yosys.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index e26eaf4be..42cfcb5bb 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -358,11 +358,19 @@ void yosys_shutdown() RTLIL::IdString new_id(std::string file, int line, std::string func) { - std::string str = "$auto$"; +#ifdef _WIN32 + size_t pos = file.find_last_of("/\\"); +#else size_t pos = file.find_last_of('/'); - str += pos != std::string::npos ? file.substr(pos+1) : file; - str += stringf(":%d:%s$%d", line, func.c_str(), autoidx++); - return str; +#endif + if (pos != std::string::npos) + file = file.substr(pos+1); + + pos = func.find_last_of(':'); + if (pos != std::string::npos) + func = func.substr(pos+1); + + return stringf("$auto$%s:%d:%s$%d", file.c_str(), line, func.c_str(), autoidx++); } RTLIL::Design *yosys_get_design() From de8adb8ec538913b93662198cf12c0f2a3b72630 Mon Sep 17 00:00:00 2001 From: Parviz Palangpour Date: Sat, 18 Oct 2014 14:26:49 -0500 Subject: [PATCH 087/492] Builds on Mac 10.9.2 with LLVM 3.5. --- frontends/ast/ast.cc | 5 +++++ kernel/yosys.cc | 3 +++ 2 files changed, 8 insertions(+) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 87b073ff3..e41416efc 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -32,7 +32,12 @@ #include #include + +#if defined(__APPLE__) +#include +#else #include +#endif YOSYS_NAMESPACE_BEGIN diff --git a/kernel/yosys.cc b/kernel/yosys.cc index f314f546a..e9b113dd2 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -33,6 +33,9 @@ # include #elif defined(__APPLE__) # include +# include +# include +# include #else # include # include From 750c615e7f01d44db4a7d504024b3681a56d8a78 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 19 Oct 2014 18:42:03 +0200 Subject: [PATCH 088/492] minor indenting corrections --- frontends/ast/ast.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index e41416efc..7a7bd3038 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -34,9 +34,9 @@ #include #if defined(__APPLE__) -#include +# include #else -#include +# include #endif YOSYS_NAMESPACE_BEGIN From c5eb5e56b8911bb520a987761739bbb9d9328380 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 23 Oct 2014 10:47:21 +0200 Subject: [PATCH 089/492] Re-introduced Yosys::readsome() helper function (f.read() + f.gcount() made problems with lines > 16kB) --- frontends/ilang/ilang_lexer.l | 6 +----- frontends/verilog/preproc.cc | 8 +++----- frontends/verilog/verilog_lexer.l | 6 +----- kernel/yosys.cc | 16 ++++++++++++++++ kernel/yosys.h | 1 + passes/cmds/write_file.cc | 9 +++------ 6 files changed, 25 insertions(+), 21 deletions(-) diff --git a/frontends/ilang/ilang_lexer.l b/frontends/ilang/ilang_lexer.l index dcbc6b6d7..ace992fbd 100644 --- a/frontends/ilang/ilang_lexer.l +++ b/frontends/ilang/ilang_lexer.l @@ -35,11 +35,7 @@ USING_YOSYS_NAMESPACE #define YY_INPUT(buf,result,max_size) \ - do { \ - ILANG_FRONTEND::lexin->read(buf, max_size-1); \ - result = ILANG_FRONTEND::lexin->gcount(); \ - if (result >= 0) buf[result] = '\0'; \ - } while (0) + result = readsome(*ILANG_FRONTEND::lexin, buf, max_size) %} diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index da658410d..b4e77c31b 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -196,16 +196,14 @@ static std::string next_token(bool pass_newline = false) static void input_file(std::istream &f, std::string filename) { char buffer[513]; + int rc; insert_input(""); auto it = input_buffer.begin(); input_buffer.insert(it, "`file_push " + filename + "\n"); - while (1) { - f.read(buffer, sizeof(buffer)-1); - if (f.gcount() <= 0) - break; - buffer[f.gcount()] = 0; + while ((rc = readsome(f, buffer, sizeof(buffer)-1)) > 0) { + buffer[rc] = 0; input_buffer.insert(it, buffer); } input_buffer.insert(it, "\n`file_pop\n"); diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 0d28e2e7f..ae16ebf78 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -64,11 +64,7 @@ YOSYS_NAMESPACE_END return TOK_ID; #define YY_INPUT(buf,result,max_size) \ - do { \ - lexin->read(buf, max_size-1); \ - result = lexin->gcount(); \ - if (result >= 0) buf[result] = '\0'; \ - } while (0) + result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size) %} diff --git a/kernel/yosys.cc b/kernel/yosys.cc index ad0aa5a6d..d4365ee00 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -97,6 +97,22 @@ std::string vstringf(const char *fmt, va_list ap) return string; } +int readsome(std::istream &f, char *s, int n) +{ + int rc = f.readsome(s, n); + + // f.readsome() sometimes returns 0 on a non-empty stream.. + if (rc == 0) { + int c = f.get(); + if (c != EOF) { + *s = c; + rc = 1; + } + } + + return rc; +} + std::string next_token(std::string &text, const char *sep) { size_t pos_begin = text.find_first_not_of(sep); diff --git a/kernel/yosys.h b/kernel/yosys.h index b9182c1df..11f356adc 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -127,6 +127,7 @@ namespace RTLIL { std::string stringf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); std::string vstringf(const char *fmt, va_list ap); +int readsome(std::istream &f, char *s, int n); std::string next_token(std::string &text, const char *sep); bool patmatch(const char *pattern, const char *string); int run_command(const std::string &command, std::function process_line = std::function()); diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc index 9bf1a75a8..25ec4acc2 100644 --- a/passes/cmds/write_file.cc +++ b/passes/cmds/write_file.cc @@ -68,13 +68,10 @@ struct WriteFileFrontend : public Frontend { FILE *of = fopen(output_filename.c_str(), append_mode ? "a" : "w"); char buffer[64 * 1024]; + int bytes; - while (1) { - f->read(buffer, sizeof(buffer)); - if (f->gcount() <= 0) - break; - fwrite(buffer, f->gcount(), 1, of); - } + while (0 < (bytes = readsome(*f, buffer, sizeof(buffer)))) + fwrite(buffer, bytes, 1, of); fclose(of); } From 26cbe4a4e56c0b95483b7568914d0402ef955b72 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 25 Oct 2014 18:23:53 +0200 Subject: [PATCH 090/492] Fixed constant "cond ? string1 : string2" with strings of different size --- frontends/ast/ast.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 7a7bd3038..56ea64eff 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -706,6 +706,8 @@ AstNode *AstNode::mkconst_bits(const std::vector &v, bool is_signe AstNode *AstNode::mkconst_str(const std::vector &v) { AstNode *node = mkconst_str(RTLIL::Const(v).decode_string()); + while (GetSize(node->bits) < GetSize(v)) + node->bits.push_back(RTLIL::State::S0); log_assert(node->bits == v); return node; } From 70b2efdb05f24eb7a9f3e2f456e5452fff94a15e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 26 Oct 2014 20:33:10 +0100 Subject: [PATCH 091/492] Added support for $readmemh/$readmemb --- README | 1 - frontends/ast/ast.h | 1 + frontends/ast/simplify.cc | 112 ++++++++++++++++++++++++++++++++++++++ kernel/rtlil.cc | 2 +- 4 files changed, 114 insertions(+), 2 deletions(-) diff --git a/README b/README index 32a47cbfe..1eb6f10aa 100644 --- a/README +++ b/README @@ -384,7 +384,6 @@ Other Unsorted TODOs - Implement missing Verilog 2005 features: - Support for real (float) const. expressions and parameters - - ROM modeling using $readmemh/$readmemb in "initial" blocks - Ignore what needs to be ignored (e.g. drive and charge strengths) - Check standard vs. implementation to identify missing features diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 56f5d888d..023755387 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -204,6 +204,7 @@ namespace AST // simplify() creates a simpler AST by unrolling for-loops, expanding generate blocks, etc. // it also sets the id2ast pointers so that identifier lookups are fast in genRTLIL() bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param); + AstNode *readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr); void expand_genblock(std::string index_var, std::string prefix, std::map &name_map); void replace_ids(const std::string &prefix, const std::map &rules); void mem2reg_as_needed_pass1(std::map> &mem2reg_places, diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index e2d63de60..f16c3d067 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -28,10 +28,12 @@ #include "kernel/log.h" #include "libs/sha1/sha1.h" +#include "frontends/verilog/verilog_frontend.h" #include "ast.h" #include #include +#include #include YOSYS_NAMESPACE_BEGIN @@ -1480,6 +1482,44 @@ skip_dynamic_range_lvalue_expansion:; log_error("Can't resolve function name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum); } if (type == AST_TCALL) { + if (str == "\\$readmemh" || str == "\\$readmemb") + { + if (GetSize(children) < 2 || GetSize(children) > 4) + log_error("System function %s got %d arguments, expected 2-4 at %s:%d.\n", + RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum); + + AstNode *node_filename = children[0]->clone(); + while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } + if (node_filename->type != AST_CONSTANT) + log_error("Failed to evaluate system function `%s' with non-constant 1st argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + + AstNode *node_memory = children[1]->clone(); + while (node_memory->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } + if (node_memory->type != AST_IDENTIFIER || node_memory->id2ast == nullptr || node_memory->id2ast->type != AST_MEMORY) + log_error("Failed to evaluate system function `%s' with non-memory 2nd argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + + int start_addr = -1, finish_addr = -1; + + if (GetSize(children) > 2) { + AstNode *node_addr = children[2]->clone(); + while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } + if (node_addr->type != AST_CONSTANT) + log_error("Failed to evaluate system function `%s' with non-constant 3rd argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + start_addr = node_addr->asInt(false); + } + + if (GetSize(children) > 3) { + AstNode *node_addr = children[3]->clone(); + while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } + if (node_addr->type != AST_CONSTANT) + log_error("Failed to evaluate system function `%s' with non-constant 4th argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + finish_addr = node_addr->asInt(false); + } + + newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr); + goto apply_newNode; + } + if (current_scope.count(str) == 0 || current_scope[str]->type != AST_TASK) log_error("Can't resolve task name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum); } @@ -1988,6 +2028,78 @@ static void replace_result_wire_name_in_function(AstNode *node, std::string &fro node->str = to; } +// replace a readmem[bh] TCALL ast node with a block of memory assignments +AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr) +{ + AstNode *block = new AstNode(AST_BLOCK); + + std::ifstream f; + f.open(mem_filename.c_str()); + + if (f.fail()) + log_error("Can not open file `%s` for %s at %s:%d.\n", mem_filename.c_str(), str.c_str(), filename.c_str(), linenum); + + // log_assert(GetSize(memory->children) == 2 && memory->children[0]->type == AST_RANGE && memory->children[0]->range_valid); + // int wordsize_left = memory->children[0]->range_left, wordsize_right = memory->children[0]->range_right; + // int wordsize = std::max(wordsize_left, wordsize_right) - std::min(wordsize_left, wordsize_right) + 1; + + bool in_comment = false; + int increment = (start_addr < finish_addr) || (start_addr < 0) || (finish_addr < 0) ? +1 : -1; + int cursor = start_addr < 0 ? 0 : start_addr; + + while (!f.eof()) + { + std::string line, token; + std::getline(f, line); + + for (int i = 0; i < GetSize(line); i++) { + if (in_comment && line.substr(i, 2) == "*/") { + line[i] = ' '; + line[i+1] = ' '; + in_comment = false; + continue; + } + if (!in_comment && line.substr(i, 2) == "/*") + in_comment = true; + if (in_comment) + line[i] = ' '; + } + + while (1) + { + token = next_token(line, " \t\r\n"); + if (token.empty() || token.substr(0, 2) == "//") + break; + + if (token[0] == '@') { + token = token.substr(1); + const char *nptr = token.c_str(); + char *endptr; + cursor = strtol(nptr, &endptr, 16); + if (!*nptr || *endptr) + log_error("Can not parse address `%s` for %s at %s:%d.\n", nptr, str.c_str(), filename.c_str(), linenum); + continue; + } + + AstNode *value = VERILOG_FRONTEND::const2ast((is_readmemh ? "'h" : "'b") + token); + + block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor, false))), value)); + block->children.back()->children[0]->str = memory->str; + block->children.back()->children[0]->id2ast = memory; + + if (cursor == finish_addr) + break; + cursor += increment; + } + + if (cursor == finish_addr) + break; + } + + // fixme + return block; +} + // annotate the names of all wires and other named objects in a generate block void AstNode::expand_genblock(std::string index_var, std::string prefix, std::map &name_map) { diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 1a9eb4d14..8cfc0c5f9 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2935,7 +2935,7 @@ bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::stri if (netname.size() == 0) continue; - if ('0' <= netname[0] && netname[0] <= '9') { + if (('0' <= netname[0] && netname[0] <= '9') || netname[0] == '\'') { cover("kernel.rtlil.sigspec.parse.const"); AST::get_line_num = sigspec_parse_get_dummy_line_num; AST::AstNode *ast = VERILOG_FRONTEND::const2ast(netname); From c4a2b3c1e9be01a0b7cf7d2cc8b91aea72d7830c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 26 Oct 2014 23:29:36 +0100 Subject: [PATCH 092/492] Improvements in $readmem[bh] implementation --- frontends/ast/simplify.cc | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index f16c3d067..75a2a2364 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2039,13 +2039,19 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m if (f.fail()) log_error("Can not open file `%s` for %s at %s:%d.\n", mem_filename.c_str(), str.c_str(), filename.c_str(), linenum); - // log_assert(GetSize(memory->children) == 2 && memory->children[0]->type == AST_RANGE && memory->children[0]->range_valid); - // int wordsize_left = memory->children[0]->range_left, wordsize_right = memory->children[0]->range_right; - // int wordsize = std::max(wordsize_left, wordsize_right) - std::min(wordsize_left, wordsize_right) + 1; + log_assert(GetSize(memory->children) == 2 && memory->children[1]->type == AST_RANGE && memory->children[1]->range_valid); + int range_left = memory->children[1]->range_left, range_right = memory->children[1]->range_right; + int range_min = std::min(range_left, range_right), range_max = std::max(range_left, range_right); + + if (start_addr < 0) + start_addr = range_min; + + if (finish_addr < 0) + finish_addr = range_max; bool in_comment = false; - int increment = (start_addr < finish_addr) || (start_addr < 0) || (finish_addr < 0) ? +1 : -1; - int cursor = start_addr < 0 ? 0 : start_addr; + int increment = start_addr <= finish_addr ? +1 : -1; + int cursor = start_addr; while (!f.eof()) { @@ -2087,16 +2093,15 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m block->children.back()->children[0]->str = memory->str; block->children.back()->children[0]->id2ast = memory; - if (cursor == finish_addr) + if ((cursor == finish_addr) || (increment > 0 && cursor >= range_max) || (increment < 0 && cursor <= range_min)) break; cursor += increment; } - if (cursor == finish_addr) + if ((cursor == finish_addr) || (increment > 0 && cursor >= range_max) || (increment < 0 && cursor <= range_min)) break; } - // fixme return block; } From f9c096eedabdf7cd2cdd770da73bdd17d86559e7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 27 Oct 2014 13:21:57 +0100 Subject: [PATCH 093/492] Added support for task and function args in parentheses --- frontends/verilog/verilog_parser.y | 51 ++++++++++++++++++++++++++---- tests/simple/task_func.v | 36 ++++++++++++++++++++- 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index cf02a56a9..e1304bff2 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -449,7 +449,7 @@ task_func_decl: } opt_dpi_function_args ';' { current_function_or_task = NULL; } | - attr TOK_TASK TOK_ID ';' { + attr TOK_TASK TOK_ID { current_function_or_task = new AstNode(AST_TASK); current_function_or_task->str = *$3; append_attr(current_function_or_task, $1); @@ -457,11 +457,11 @@ task_func_decl: ast_stack.push_back(current_function_or_task); current_function_or_task_port_id = 1; delete $3; - } task_func_body TOK_ENDTASK { + } task_func_args_opt ';' task_func_body TOK_ENDTASK { current_function_or_task = NULL; ast_stack.pop_back(); } | - attr TOK_FUNCTION opt_signed range_or_signed_int TOK_ID ';' { + attr TOK_FUNCTION opt_signed range_or_signed_int TOK_ID { current_function_or_task = new AstNode(AST_FUNCTION); current_function_or_task->str = *$5; append_attr(current_function_or_task, $1); @@ -478,7 +478,7 @@ task_func_decl: current_function_or_task->children.push_back(outreg); current_function_or_task_port_id = 1; delete $5; - } task_func_body TOK_ENDFUNCTION { + } task_func_args_opt ';' task_func_body TOK_ENDFUNCTION { current_function_or_task = NULL; ast_stack.pop_back(); }; @@ -512,6 +512,45 @@ opt_signed: $$ = false; }; +task_func_args_opt: + '(' ')' | /* empty */ | '(' { + albuf = nullptr; + astbuf1 = nullptr; + astbuf2 = nullptr; + } task_func_args optional_comma { + delete astbuf1; + if (astbuf2 != NULL) + delete astbuf2; + free_attr(albuf); + } ')'; + +task_func_args: + task_func_port | task_func_args ',' task_func_port; + +task_func_port: + attr wire_type range { + if (albuf) { + delete astbuf1; + if (astbuf2 != NULL) + delete astbuf2; + free_attr(albuf); + } + albuf = $1; + astbuf1 = $2; + astbuf2 = $3; + if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { + if (astbuf2) { + frontend_verilog_yyerror("Syntax error."); + } else { + astbuf2 = new AstNode(AST_RANGE); + astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); + astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true)); + } + } + if (astbuf2 && astbuf2->children.size() != 2) + frontend_verilog_yyerror("Syntax error."); + } wire_name | wire_name; + task_func_body: task_func_body behavioral_stmt | /* empty */; @@ -609,12 +648,12 @@ wire_decl: } if (astbuf2 && astbuf2->children.size() != 2) frontend_verilog_yyerror("Syntax error."); - } wire_name_list ';' { + } wire_name_list { delete astbuf1; if (astbuf2 != NULL) delete astbuf2; free_attr(albuf); - } | + } ';' | attr TOK_SUPPLY0 TOK_ID ';' { ast_stack.back()->children.push_back(new AstNode(AST_WIRE)); ast_stack.back()->children.back()->str = *$3; diff --git a/tests/simple/task_func.v b/tests/simple/task_func.v index 51e31015f..9b8e26e51 100644 --- a/tests/simple/task_func.v +++ b/tests/simple/task_func.v @@ -33,8 +33,42 @@ end endmodule +// ------------------------------------------------------------------- -module task_func_test02( input [7:0] din_a, input [7:0] din_b, output [7:0] dout_a); +module task_func_test02(clk, a, b, c, x, y, z, w); + +input clk; +input [7:0] a, b, c; +output reg [7:0] x, y, z, w; + +function [7:0] sum_shift(input [3:0] s1, s2, s3); +sum_shift = s1 + (s2 << 2) + (s3 << 4); +endfunction + +task reset_w; +w = 0; +endtask + +task add_to(output [7:0] out, input [7:0] in); +out = out + in; +endtask + +always @(posedge clk) begin + x = sum_shift(a, b, c); + y = sum_shift(a[7:4], b[5:2], c[3:0]); + z = sum_shift(a[0], b[5:4], c >> 5) ^ sum_shift(1, 2, 3); + + reset_w; + add_to(w, x); + add_to(w, y); + add_to(w, z); +end + +endmodule + +// ------------------------------------------------------------------- + +module task_func_test03( input [7:0] din_a, input [7:0] din_b, output [7:0] dout_a); assign dout_a = test(din_a,din_b); function [7:0] test; input [7:0] a; From 37aa2e02db2f3070a153a1de04c0ce99d1369adb Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 29 Oct 2014 08:29:51 +0100 Subject: [PATCH 094/492] AST simplifier: optimize constant AST_CASE nodes before recursively descending --- frontends/ast/simplify.cc | 66 +++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 75a2a2364..d8fdb4c5e 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -384,6 +384,41 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } } + if (const_fold && type == AST_CASE) + { + while (children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { } + if (children[0]->type == AST_CONSTANT && children[0]->bits_only_01()) { + std::vector new_children; + new_children.push_back(children[0]); + for (int i = 1; i < GetSize(children); i++) { + AstNode *child = children[i]; + log_assert(child->type == AST_COND); + for (auto v : child->children) { + if (v->type == AST_DEFAULT) + goto keep_const_cond; + if (v->type == AST_BLOCK) + continue; + while (v->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { } + if (v->type == AST_CONSTANT && v->bits_only_01()) { + if (v->bits == children[0]->bits) { + while (i+1 < GetSize(children)) + delete children[++i]; + goto keep_const_cond; + } + continue; + } + goto keep_const_cond; + } + if (0) + keep_const_cond: + new_children.push_back(child); + else + delete child; + } + new_children.swap(children); + } + } + // simplify all children first // (iterate by index as e.g. auto wires can add new children in the process) for (size_t i = 0; i < children.size(); i++) { @@ -1883,37 +1918,6 @@ skip_dynamic_range_lvalue_expansion:; newNode->realvalue = -children[0]->asReal(sign_hint); } break; - case AST_CASE: - if (children[0]->type == AST_CONSTANT && children[0]->bits_only_01()) { - std::vector new_children; - new_children.push_back(children[0]); - for (int i = 1; i < GetSize(children); i++) { - AstNode *child = children[i]; - log_assert(child->type == AST_COND); - for (auto v : child->children) { - if (v->type == AST_DEFAULT) - goto keep_const_cond; - if (v->type == AST_BLOCK) - continue; - if (v->type == AST_CONSTANT && v->bits_only_01()) { - if (v->bits == children[0]->bits) { - while (i+1 < GetSize(children)) - delete children[++i]; - goto keep_const_cond; - } - continue; - } - goto keep_const_cond; - } - if (0) - keep_const_cond: - new_children.push_back(child); - else - delete child; - } - new_children.swap(children); - } - break; case AST_TERNARY: if (children[0]->isConst()) { From 269e37e969562275f337362b5423e2801f9c5765 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 29 Oct 2014 09:05:17 +0100 Subject: [PATCH 095/492] Added support for empty lines to here documents --- kernel/register.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/register.cc b/kernel/register.cc index 33c129d83..2927a333e 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -333,8 +333,8 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector 0 && (buffer[buffer.size() - 1] == '\n' || buffer[buffer.size() - 1] == '\r')) break; } - int indent = buffer.find_first_not_of(" \t\r\n"); - if (buffer.substr(indent, eot_marker.size()) == eot_marker) + size_t indent = buffer.find_first_not_of(" \t\r\n"); + if (indent != std::string::npos && buffer.substr(indent, eot_marker.size()) == eot_marker) break; last_here_document += buffer; } From ac8f4d298b3cc351fa0658857e11069a67adb7ba Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 30 Oct 2014 09:12:55 +0100 Subject: [PATCH 096/492] Improved nomem2reg documentation --- README | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README b/README index 1eb6f10aa..d90a11935 100644 --- a/README +++ b/README @@ -248,7 +248,10 @@ Verilog Attributes and non-standard features is strongly recommended instead). - The "nomem2reg" attribute on modules or arrays prohibits the - automatic early conversion of arrays to separate registers. + automatic early conversion of arrays to separate registers. This + is potentially dangerous. Usually the front-end has good reasons + for converting an array to a list of registers. Prohibiting this + step will likely result in incorrect synthesis results. - The "mem2reg" attribute on modules or arrays forces the early conversion of arrays to separate registers. From a21481b338933f9498fd0fb11492aa2e5b7a00cd Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 30 Oct 2014 14:01:02 +0100 Subject: [PATCH 097/492] Fixed parsing of "module mymod #( parameter foo = 1, bar = 2 ..." --- frontends/verilog/verilog_parser.y | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index e1304bff2..0902e58a2 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -240,7 +240,7 @@ module: }; module_para_opt: - '#' '(' module_para_list ')' | /* empty */; + '#' '(' { astbuf1 = nullptr; } module_para_list { if (astbuf1) delete astbuf1; } ')' | /* empty */; module_para_list: single_module_para | @@ -249,11 +249,10 @@ module_para_list: single_module_para: TOK_PARAMETER { + if (astbuf1) delete astbuf1; astbuf1 = new AstNode(AST_PARAMETER); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); - } param_signed param_integer param_range single_param_decl { - delete astbuf1; - }; + } param_signed param_integer param_range single_param_decl | single_param_decl; module_args_opt: '(' ')' | /* empty */ | '(' module_args optional_comma ')'; @@ -607,6 +606,8 @@ param_decl_list: single_param_decl: TOK_ID '=' expr { + if (astbuf1 == nullptr) + frontend_verilog_yyerror("syntax error"); AstNode *node = astbuf1->clone(); node->str = *$1; delete node->children[0]; From ab28491f271e3b02ba58dabb4b7033bcf17b6c25 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 31 Oct 2014 03:36:51 +0100 Subject: [PATCH 098/492] Added "opt -full" alias for all more aggressive optimizations --- passes/opt/opt.cc | 13 +++++++++---- passes/opt/opt_const.cc | 16 +++++++++++++--- passes/opt/opt_reduce.cc | 7 +++++++ techlibs/common/synth.cc | 8 ++++++-- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/passes/opt/opt.cc b/passes/opt/opt.cc index ea454b333..83a30ad77 100644 --- a/passes/opt/opt.cc +++ b/passes/opt/opt.cc @@ -37,22 +37,22 @@ struct OptPass : public Pass { log("a series of trivial optimizations and cleanups. This pass executes the other\n"); log("passes in the following order:\n"); log("\n"); - log(" opt_const [-mux_undef] [-mux_bool] [-undriven] [-fine] [-keepdc]\n"); + log(" opt_const [-mux_undef] [-mux_bool] [-undriven] [-fine] [-full] [-keepdc]\n"); log(" opt_share -nomux\n"); log("\n"); log(" do\n"); log(" opt_muxtree\n"); - log(" opt_reduce [-fine]\n"); + log(" opt_reduce [-fine] [-full]\n"); log(" opt_share\n"); log(" opt_rmdff\n"); log(" opt_clean [-purge]\n"); - log(" opt_const [-mux_undef] [-mux_bool] [-undriven] [-fine] [-keepdc]\n"); + log(" opt_const [-mux_undef] [-mux_bool] [-undriven] [-fine] [-full] [-keepdc]\n"); log(" while \n"); log("\n"); log("When called with -fast the following script is used instead:\n"); log("\n"); log(" do\n"); - log(" opt_const [-mux_undef] [-mux_bool] [-undriven] [-fine] [-keepdc]\n"); + log(" opt_const [-mux_undef] [-mux_bool] [-undriven] [-fine] [-full] [-keepdc]\n"); log(" opt_share\n"); log(" opt_rmdff\n"); log(" opt_clean [-purge]\n"); @@ -96,6 +96,11 @@ struct OptPass : public Pass { opt_reduce_args += " -fine"; continue; } + if (args[argidx] == "-full") { + opt_const_args += " -full"; + opt_reduce_args += " -full"; + continue; + } if (args[argidx] == "-keepdc") { opt_const_args += " -keepdc"; continue; diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc index c726c7b3d..e00d5e3b1 100644 --- a/passes/opt/opt_const.cc +++ b/passes/opt/opt_const.cc @@ -942,15 +942,18 @@ struct OptConstPass : public Pass { log(" -undriven\n"); log(" replace undriven nets with undef (x) constants\n"); log("\n"); + log(" -fine\n"); + log(" perform fine-grain optimizations\n"); + log("\n"); + log(" -full\n"); + log(" alias for -mux_undef -mux_bool -undriven -fine\n"); + log("\n"); log(" -keepdc\n"); log(" some optimizations change the behavior of the circuit with respect to\n"); log(" don't-care bits. for example in 'a+0' a single x-bit in 'a' will cause\n"); log(" all result bits to be set to x. this behavior changes when 'a+0' is\n"); log(" replaced by 'a'. the -keepdc option disables all such optimizations.\n"); log("\n"); - log(" -fine\n"); - log(" perform fine-grain optimizations\n"); - log("\n"); } virtual void execute(std::vector args, RTLIL::Design *design) { @@ -981,6 +984,13 @@ struct OptConstPass : public Pass { do_fine = true; continue; } + if (args[argidx] == "-full") { + mux_undef = true; + mux_bool = true; + undriven = true; + do_fine = true; + continue; + } if (args[argidx] == "-keepdc") { keepdc = true; continue; diff --git a/passes/opt/opt_reduce.cc b/passes/opt/opt_reduce.cc index 302deb9bd..3183d973d 100644 --- a/passes/opt/opt_reduce.cc +++ b/passes/opt/opt_reduce.cc @@ -346,6 +346,9 @@ struct OptReducePass : public Pass { log(" -fine\n"); log(" perform fine-grain optimizations\n"); log("\n"); + log(" -full\n"); + log(" alias for -fine\n"); + log("\n"); } virtual void execute(std::vector args, RTLIL::Design *design) { @@ -359,6 +362,10 @@ struct OptReducePass : public Pass { do_fine = true; continue; } + if (args[argidx] == "-full") { + do_fine = true; + continue; + } break; } extra_args(args, argidx, design); diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 8b41a003d..c76b002cc 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -76,9 +76,11 @@ struct SynthPass : public Pass { log(" opt_clean\n"); log("\n"); log(" fine:\n"); + log(" opt -fast -full\n"); log(" memory_map\n"); + log(" opt -full\n"); log(" techmap\n"); - log(" opt -fast\n"); + log(" opt -fast -full\n"); #ifdef YOSYS_ENABLE_ABC log(" abc -fast\n"); log(" opt_clean\n"); @@ -144,9 +146,11 @@ struct SynthPass : public Pass { if (check_label(active, run_from, run_to, "fine")) { + Pass::call(design, "opt -fast -full"); Pass::call(design, "memory_map"); + Pass::call(design, "opt -full"); Pass::call(design, "techmap"); - Pass::call(design, "opt -fast"); + Pass::call(design, "opt -fast -full"); #ifdef YOSYS_ENABLE_ABC Pass::call(design, "abc -fast"); Pass::call(design, "opt_clean"); From 74ef92b9c888fd05f03b4f679ecda6b04249e498 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 31 Oct 2014 03:46:27 +0100 Subject: [PATCH 099/492] Added "abc" label in synth script --- techlibs/common/synth.cc | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index c76b002cc..211b5905a 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -80,10 +80,12 @@ struct SynthPass : public Pass { log(" memory_map\n"); log(" opt -full\n"); log(" techmap\n"); - log(" opt -fast -full\n"); + log(" opt -fast\n"); #ifdef YOSYS_ENABLE_ABC + log("\n"); + log(" abc:\n"); log(" abc -fast\n"); - log(" opt_clean\n"); + log(" opt -fast\n"); #endif log("\n"); } @@ -150,13 +152,17 @@ struct SynthPass : public Pass { Pass::call(design, "memory_map"); Pass::call(design, "opt -full"); Pass::call(design, "techmap"); - Pass::call(design, "opt -fast -full"); - #ifdef YOSYS_ENABLE_ABC - Pass::call(design, "abc -fast"); - Pass::call(design, "opt_clean"); - #endif + Pass::call(design, "opt -fast"); } + #ifdef YOSYS_ENABLE_ABC + if (check_label(active, run_from, run_to, "abc")) + { + Pass::call(design, "abc -fast"); + Pass::call(design, "opt -fast"); + } + #endif + log_pop(); } } SynthPass; From 80869531b91b0fd8da90a1bebdc8d81d35e36e23 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 5 Nov 2014 10:37:37 +0100 Subject: [PATCH 100/492] Removed QMAKE variable from Makefile --- Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Makefile b/Makefile index f3f304ce1..7733dbcbe 100644 --- a/Makefile +++ b/Makefile @@ -33,14 +33,12 @@ all: top-all CXXFLAGS = -Wall -Wextra -ggdb -I"$(shell pwd)" -MD -DYOSYS_SRC='"$(shell pwd)"' -D_YOSYS_ -fPIC -I${DESTDIR}/include LDFLAGS = -L${DESTDIR}/lib LDLIBS = -lstdc++ -lm -QMAKE = qmake-qt4 SED = sed ifeq (Darwin,$(findstring Darwin,$(shell uname))) # add macports include and library path to search directories, don't use '-rdynamic' and '-lrt': CXXFLAGS += -I/opt/local/include LDFLAGS += -L/opt/local/lib - QMAKE = qmake SED = gsed else LDFLAGS += -rdynamic From a346c0bf2b0ed5278e0f86d4ef23a6a9d03eef40 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 6 Nov 2014 09:39:55 +0100 Subject: [PATCH 101/492] Made "cover" a compile-time option (disabled by default) --- Makefile | 5 +++++ kernel/driver.cc | 2 +- kernel/log.cc | 2 +- kernel/log.h | 3 +-- passes/cmds/cover.cc | 4 ++-- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 7733dbcbe..c1944f2e3 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ ENABLE_ABC := 1 ENABLE_PLUGINS := 1 ENABLE_READLINE := 1 ENABLE_VERIFIC := 0 +ENABLE_COVER := 0 # other configuration flags ENABLE_GPROF := 0 @@ -138,6 +139,10 @@ CXXFLAGS += $(patsubst %,-I$(VERIFIC_DIR)/%,$(VERIFIC_COMPONENTS)) -DYOSYS_ENABL LDLIBS += $(patsubst %,$(VERIFIC_DIR)/%/*-linux.a,$(VERIFIC_COMPONENTS)) endif +ifeq ($(ENABLE_COVER),1) +CXXFLAGS += -DYOSYS_ENABLE_COVER +endif + ifeq ($(PRETTY), 1) P_STATUS = 0 P_OFFSET = 0 diff --git a/kernel/driver.cc b/kernel/driver.cc index 5e69cced3..8164fef28 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -335,7 +335,7 @@ int main(int argc, char **argv) log("%s\n", out_count ? "" : " no commands executed"); } -#ifdef COVER_ACTIVE +#ifdef YOSYS_ENABLE_COVER if (getenv("YOSYS_COVER_DIR") || getenv("YOSYS_COVER_FILE")) { char filename_buffer[4096]; diff --git a/kernel/log.cc b/kernel/log.cc index 807f58bf6..1a21e9fe6 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -274,7 +274,7 @@ void log_cell(RTLIL::Cell *cell, std::string indent) // --------------------------------------------------- // This is the magic behind the code coverage counters // --------------------------------------------------- -#ifdef COVER_ACTIVE +#ifdef YOSYS_ENABLE_COVER std::map> extra_coverage_data; diff --git a/kernel/log.h b/kernel/log.h index 81d01ace7..a6f808922 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -87,8 +87,7 @@ static inline void log_assert_worker(bool cond, const char *expr, const char *fi // This is the magic behind the code coverage counters // --------------------------------------------------- -#if defined(__linux__) && !defined(NDEBUG) -#define COVER_ACTIVE +#ifdef YOSYS_ENABLE_COVER #define cover(_id) do { \ static CoverData __d __attribute__((section("yosys_cover_list"), aligned(1))) = { __FILE__, __FUNCTION__, _id, __LINE__, 0 }; \ diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc index b8baaf3d8..6a70d1de9 100644 --- a/passes/cmds/cover.cc +++ b/passes/cmds/cover.cc @@ -128,7 +128,7 @@ struct CoverPass : public Pass { log("\n"); } -#ifdef COVER_ACTIVE +#ifdef YOSYS_ENABLE_COVER for (auto &it : get_coverage_data()) { if (!patterns.empty()) { for (auto &p : patterns) @@ -146,7 +146,7 @@ struct CoverPass : public Pass { for (auto f : out_files) fclose(f); - log_cmd_error("Coverage counters are only available in debug builds of Yosys for Linux.\n"); + log_cmd_error("This version of Yosys was not built with support for code coverage counters.\n"); #endif for (auto f : out_files) From 99cdfb31106cc399072f129d912fa8377d919e2e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 7 Nov 2014 12:48:15 +0100 Subject: [PATCH 102/492] Fixed typo in "log_cmd_error_exception" --- kernel/log.cc | 2 +- kernel/log.h | 2 +- kernel/yosys.cc | 6 +++--- passes/cmds/tee.cc | 4 ++-- passes/cmds/trace.cc | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/kernel/log.cc b/kernel/log.cc index 1a21e9fe6..99e92e44d 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -194,7 +194,7 @@ void log_cmd_error(const char *format, ...) log("ERROR: "); logv(format, ap); log_flush(); - throw log_cmd_error_expection(); + throw log_cmd_error_exception(); } logv_error(format, ap); diff --git a/kernel/log.h b/kernel/log.h index a6f808922..707497a99 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -38,7 +38,7 @@ YOSYS_NAMESPACE_BEGIN #define S__LINE__sub1(x) S__LINE__sub2(x) #define S__LINE__ S__LINE__sub1(__LINE__) -struct log_cmd_error_expection { }; +struct log_cmd_error_exception { }; extern std::vector log_files; extern std::vector log_streams; diff --git a/kernel/yosys.cc b/kernel/yosys.cc index d4365ee00..6cc643152 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -668,9 +668,9 @@ void run_frontend(std::string filename, std::string command, RTLIL::Design *desi Pass::call(design, command); } } - catch (log_cmd_error_expection) { + catch (log_cmd_error_exception) { Frontend::current_script_file = backup_script_file; - throw log_cmd_error_expection(); + throw log_cmd_error_exception(); } Frontend::current_script_file = backup_script_file; @@ -852,7 +852,7 @@ void shell(RTLIL::Design *design) try { log_assert(design->selection_stack.size() == 1); Pass::call(design, command); - } catch (log_cmd_error_expection) { + } catch (log_cmd_error_exception) { while (design->selection_stack.size() > 1) design->selection_stack.pop_back(); log_reset_stack(); diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc index 8ef4c89e7..e83c93871 100644 --- a/passes/cmds/tee.cc +++ b/passes/cmds/tee.cc @@ -76,11 +76,11 @@ struct TeePass : public Pass { try { std::vector new_args(args.begin() + argidx, args.end()); Pass::call(design, new_args); - } catch (log_cmd_error_expection) { + } catch (log_cmd_error_exception) { for (auto cf : files_to_close) fclose(cf); log_files = backup_log_files; - throw log_cmd_error_expection(); + throw log_cmd_error_exception(); } for (auto cf : files_to_close) diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc index ac61be081..10c67195f 100644 --- a/passes/cmds/trace.cc +++ b/passes/cmds/trace.cc @@ -85,9 +85,9 @@ struct TracePass : public Pass { try { std::vector new_args(args.begin() + argidx, args.end()); Pass::call(design, new_args); - } catch (log_cmd_error_expection) { + } catch (log_cmd_error_exception) { design->monitors.erase(&monitor); - throw log_cmd_error_expection(); + throw log_cmd_error_exception(); } design->monitors.erase(&monitor); From c529d4fc53ddbb96dd98f5d5fef37b4b5caa1896 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 7 Nov 2014 13:34:05 +0100 Subject: [PATCH 103/492] Changelog for Yosys 0.4 --- CHANGELOG | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 356957297..9821be86f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,13 +3,82 @@ List of changes and major improvements between releases ======================================================= -Yosys 0.3.0 .. Yoys 0.3.0+ --------------------------- +Yosys 0.3.0 .. Yosys 0.4 +------------------------ - ... TBD ... + * Platform Support + - Added support for mxe-based cross-builds for win32 + - Added sourcecode-export as VisualStudio project + - Added experimental EMCC (JavaScript) support + + * Verilog Frontend + - Added -sv option for SystemVerilog (and automatic *.sv file support) + - Added support for real-valued constants and constant expressions + - Added support for non-standard "via_celltype" attribute on task/func + - Added support for non-standard "module mod_name(...);" syntax + - Added support for non-standard """ macro bodies + - Added support for array with more than one dimension + - Added support for $readmemh and $readmemb + - Added support for DPI functions + + * Changes in internal cell library + - Added $shift and $shiftx cell types + - Added $alu, $lcu, $fa and $macc cell types + - Removed $bu0 and $safe_pmux cell types + - $mem/$memwr WR_EN input is now a per-data-bit enable signal + - Added $_NAND_ $_NOR_ $_XNOR_ $_AOI3_ $_OAI3_ $_AOI4_ $_OAI4_ + - Renamed ports of $lut cells (from I->O to A->Y) + - Renamed $_INV_ to $_NOT_ + + * Changes for simple synthesis flows + - There is now a "synth" command with a recommended default script + - Many improvements in synthesis of arithmetic functions to gates + - Multiplieres and adders with many operands are using carry-save adder trees + - Remaining adders are now implemented using Brent–Kung carry look-ahead adders + - Various new high-level optimizations on RTL netlist + - Various improvements in FSM optimization + - Updated ABC to hg 930a4de962a1 (from 2014-10-14) + + * Changes in internal APIs and RTLIL + - Added log_id() and log_cell() helper functions + - Added function-like cell creation helpers + - Added GetSize() function (like .size() but with int) + - Major refactoring of RTLIL::Module and related classes + - Major refactoring of RTLIL::SigSpec and related classes + - Now RTLIL::IdString is essentially an int + - Added macros for code coverage counters + - Added some Makefile magic for pretty make logs + - Added "kernel/yosys.h" with all the core definitions + - Chanded a lot of code from FILE* to c++ streams + - Added RTLIL::Monitor API and "trace" command + - Added "Yosys" C++ namespace + + * Changes relevant to SAT solving + - Added ezSAT::keep_cnf() and ezSAT::non_incremental() + - Added native ezSAT support for vector shift ops + - Updated MiniSAT to git 37dc6c67e2 (from 2013-09-25) + + * New commands (or large improvements to commands) + - Added "synth" command with default script + - Added "share" (finally some real resource sharing) + - Added "memory_share" (reduce number of ports on memories) + - Added "wreduce" and "alumacc" commands + - Added "opt -keepdc -fine -full -fast" + - Added some "test_*" commands + + * Various other changes + - Added %D and %c select operators + - Added support for labels in yosys scripts + - Added support for here-documents in yosys scripts + - Support "+/" prefix for files from proc_share_dir + - Added "autoidx" statement to ilang language + - Switched from "yosys-svgviewer" to "xdot" + - Renamed "stdcells.v" to "techmap.v" + - Various bug fixes and small improvements + - Improved welcome and bye messages -Yosys 0.2.0 .. Yoys 0.3.0 +Yosys 0.2.0 .. Yosys 0.3.0 -------------------------- * Driver program and overall behavior: @@ -59,8 +128,8 @@ Yosys 0.2.0 .. Yoys 0.3.0 - Various build fixes for OSX (Darwin) and OpenBSD -Yosys 0.1.0 .. Yoys 0.2.0 -------------------------- +Yosys 0.1.0 .. Yosys 0.2.0 +-------------------------- * Changes to the driver program: - Added "yosys -h" and "yosys -H" From 4f4d729e02babd32ebf56de3e87408e05c5728bc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 7 Nov 2014 14:39:49 +0100 Subject: [PATCH 104/492] Updated ABC to 5b5af75f1dda --- CHANGELOG | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 9821be86f..8679d6c87 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -37,7 +37,7 @@ Yosys 0.3.0 .. Yosys 0.4 - Remaining adders are now implemented using Brent–Kung carry look-ahead adders - Various new high-level optimizations on RTL netlist - Various improvements in FSM optimization - - Updated ABC to hg 930a4de962a1 (from 2014-10-14) + - Updated ABC to hg 5b5af75f1dda (from 2014-11-07) * Changes in internal APIs and RTLIL - Added log_id() and log_cell() helper functions diff --git a/Makefile b/Makefile index c1944f2e3..f6f42b3f7 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ OBJS = kernel/version_$(GIT_REV).o # is just a symlink to your actual ABC working directory, as 'make mrproper' # will remove the 'abc' directory and you do not want to accidentally # delete your work on ABC.. -ABCREV = 930a4de962a1 +ABCREV = 5b5af75f1dda ABCPULL = 1 ABCMKARGS = # CC="$(CXX)" CXX="$(CXX)" From 461594bb83a3fd908bb6580763cf7f7aa37ef6a7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 7 Nov 2014 14:40:06 +0100 Subject: [PATCH 105/492] Fixed generation of temp names in verilog backend --- backends/verilog/verilog_backend.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 814c87be7..7d08cc4e0 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -51,16 +51,17 @@ void reset_auto_counter_id(RTLIL::IdString id, bool may_rename) if (*str == '$' && may_rename && !norename) auto_name_map[id] = auto_name_counter++; - if (str[0] != '_' && str[1] != 0) + if (str[0] != '\\' || str[1] != '_' || str[2] == 0) return; - for (int i = 0; str[i] != 0; i++) { - if (str[i] == '_') + + for (int i = 2; str[i] != 0; i++) { + if (str[i] == '_' && str[i+1] == 0) continue; if (str[i] < '0' || str[i] > '9') return; } - int num = atoi(str+1); + int num = atoi(str+2); if (num >= auto_name_offset) auto_name_offset = num + 1; } From 546e8b5fe7063caf0140d753d8c20614cbeae723 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 7 Nov 2014 15:21:03 +0100 Subject: [PATCH 106/492] Improved TopoSort determinism --- kernel/rtlil.h | 2 +- kernel/utils.h | 16 ++++++++-------- passes/opt/opt_const.cc | 2 +- passes/opt/share.cc | 8 +++++--- passes/techmap/techmap.cc | 2 +- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 8a4d348be..0bb1e4e84 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -216,7 +216,7 @@ namespace RTLIL // set has an influence on the algorithm. template struct compare_ptr_by_name { - bool operator()(const T *a, const T *b) { + bool operator()(const T *a, const T *b) const { return (a == nullptr || b == nullptr) ? (a < b) : (a->name < b->name); } }; diff --git a/kernel/utils.h b/kernel/utils.h index 1779a9afc..479effdc9 100644 --- a/kernel/utils.h +++ b/kernel/utils.h @@ -128,12 +128,12 @@ public: // A simple class for topological sorting // ------------------------------------------------ -template +template> struct TopoSort { bool analyze_loops, found_loops; - std::map> database; - std::set> loops; + std::map, C> database; + std::set> loops; std::vector sorted; TopoSort() @@ -145,7 +145,7 @@ struct TopoSort void node(T n) { if (database.count(n) == 0) - database[n] = std::set(); + database[n] = std::set(); } void edge(T left, T right) @@ -154,12 +154,12 @@ struct TopoSort database[right].insert(left); } - void sort_worker(const T &n, std::set &marked_cells, std::set &active_cells, std::vector &active_stack) + void sort_worker(const T &n, std::set &marked_cells, std::set &active_cells, std::vector &active_stack) { if (active_cells.count(n)) { found_loops = true; if (analyze_loops) { - std::set loop; + std::set loop; for (int i = GetSize(active_stack)-1; i >= 0; i--) { loop.insert(active_stack[i]); if (active_stack[i] == n) @@ -197,8 +197,8 @@ struct TopoSort sorted.clear(); found_loops = false; - std::set marked_cells; - std::set active_cells; + std::set marked_cells; + std::set active_cells; std::vector active_stack; for (auto &it : database) diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc index e00d5e3b1..1e59f18c1 100644 --- a/passes/opt/opt_const.cc +++ b/passes/opt/opt_const.cc @@ -198,7 +198,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons SigMap assign_map(module); std::map invert_map; - TopoSort cells; + TopoSort> cells; std::map> cell_to_inbit; std::map> outbit_to_cell; diff --git a/passes/opt/share.cc b/passes/opt/share.cc index 2496f15d3..cb7510553 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -27,6 +27,8 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +typedef RTLIL::IdString::compare_ptr_by_name cell_ptr_cmp; + struct ShareWorkerConfig { int limit; @@ -52,8 +54,8 @@ struct ShareWorker std::set recursion_state; SigMap topo_sigmap; - std::map> topo_cell_drivers; - std::map> topo_bit_drivers; + std::map, cell_ptr_cmp> topo_cell_drivers; + std::map> topo_bit_drivers; std::vector> exclusive_ctrls; @@ -937,7 +939,7 @@ struct ShareWorker ct.setup_internals(); ct.setup_stdcells(); - TopoSort toposort; + TopoSort toposort; toposort.analyze_loops = false; topo_sigmap.set(module); diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 73da6ce1d..e109c5b58 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -281,7 +281,7 @@ struct TechmapWorker SigMap sigmap(module); - TopoSort cells; + TopoSort> cells; std::map> cell_to_inbit; std::map> outbit_to_cell; From c5dbb1aa28f5fb10ebbc0696545ede6fa76ce20b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 7 Nov 2014 15:47:18 +0100 Subject: [PATCH 107/492] Minor corrections in CodingReadme --- CodingReadme | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CodingReadme b/CodingReadme index 0e3ff6949..88f16ff0a 100644 --- a/CodingReadme +++ b/CodingReadme @@ -137,7 +137,7 @@ Update the CHANGELOG file: vi CHANGELOG -Run all tests with "make config-{clang-debug,gcc-debug,gcc-4.6,release}": +Run all tests with "make config-{clang,gcc,gcc-4.6}": cd ~yosys make clean @@ -149,9 +149,8 @@ Run all tests with "make config-{clang-debug,gcc-debug,gcc-4.6,release}": make full cd ~vloghammer - make purge - make gen_issues gen_samples - make SYN_LIST="yosys" SIM_LIST="icarus yosim verilator" FULL=1 world + make purge gen_issues gen_samples + make SYN_LIST="yosys" SIM_LIST="icarus yosim verilator" REPORT_FULL=1 world chromium-browser report.html From 89be7bf52785c9a3058a0049481388ad44459174 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 7 Nov 2014 20:58:08 +0100 Subject: [PATCH 108/492] Added "used" attribute to entries in yosys_cover_list http://www.reddit.com/r/yosys/comments/2kw479/fyi_clang_350_build_error/cltgwyc http://llvm.org/bugs/show_bug.cgi?id=19474 --- kernel/log.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/log.h b/kernel/log.h index 707497a99..93e8144a0 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -90,7 +90,7 @@ static inline void log_assert_worker(bool cond, const char *expr, const char *fi #ifdef YOSYS_ENABLE_COVER #define cover(_id) do { \ - static CoverData __d __attribute__((section("yosys_cover_list"), aligned(1))) = { __FILE__, __FUNCTION__, _id, __LINE__, 0 }; \ + static CoverData __d __attribute__((section("yosys_cover_list"), aligned(1), used)) = { __FILE__, __FUNCTION__, _id, __LINE__, 0 }; \ __d.counter++; \ } while (0) From 420bc05627afe220102368fb29d717b429645869 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 8 Nov 2014 10:58:57 +0100 Subject: [PATCH 109/492] Added "Nx" syntax to "show" command for repeating SigChunks --- passes/cmds/show.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index 1413742df..715c1de56 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -209,22 +209,24 @@ struct ShowWorker std::string label_string; int pos = sig.size()-1; int idx = single_idx_count++; - for (int i = int(sig.chunks().size())-1; i >= 0; i--) { + for (int rep, i = int(sig.chunks().size())-1; i >= 0; i -= rep) { const RTLIL::SigChunk &c = sig.chunks().at(i); net = gen_signode_simple(c, false); log_assert(!net.empty()); + for (rep = 1; i-rep >= 0 && c == sig.chunks().at(i-rep); rep++) {} + std::string repinfo = rep > 1 ? stringf("%dx ", rep) : ""; if (driver) { - label_string += stringf(" %d:%d - %d:%d |", i, pos, pos-c.width+1, c.offset+c.width-1, c.offset); + label_string += stringf(" %d:%d - %s%d:%d |", i, pos, pos-c.width+1, repinfo.c_str(), c.offset+c.width-1, c.offset); net_conn_map[net].in.insert(stringf("x%d:s%d", idx, i)); - net_conn_map[net].bits = c.width; + net_conn_map[net].bits = rep*c.width; net_conn_map[net].color = nextColor(c, net_conn_map[net].color); } else { - label_string += stringf(" %d:%d - %d:%d |", i, c.offset+c.width-1, c.offset, pos, pos-c.width+1); + label_string += stringf(" %s%d:%d - %d:%d |", i, repinfo.c_str(), c.offset+c.width-1, c.offset, pos, pos-rep*c.width+1); net_conn_map[net].out.insert(stringf("x%d:s%d", idx, i)); - net_conn_map[net].bits = c.width; + net_conn_map[net].bits = rep*c.width; net_conn_map[net].color = nextColor(c, net_conn_map[net].color); } - pos -= c.width; + pos -= rep * c.width; } if (label_string[label_string.size()-1] == '|') label_string = label_string.substr(0, label_string.size()-1); From b9f2127f5d5a78bab74f511a71b6a369065a0383 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 8 Nov 2014 10:59:48 +0100 Subject: [PATCH 110/492] Various documentation updates --- CodingReadme | 1 + manual/CHAPTER_Appnotes.tex | 25 +- manual/CHAPTER_Auxprogs.tex | 6 + manual/PRESENTATION_ExAdv.tex | 2 +- manual/PRESENTATION_ExOth/axis_master.v | 2 +- manual/PRESENTATION_ExSyn.tex | 6 +- manual/PRESENTATION_Intro.tex | 65 +- manual/PRESENTATION_Prog.tex | 79 +- manual/PRESENTATION_Prog/my_cmd.cc | 7 +- manual/command-reference-manual.tex | 1183 ++++++++++++++++++++++- manual/manual.tex | 5 +- manual/presentation.sh | 2 + manual/presentation.tex | 2 +- 13 files changed, 1277 insertions(+), 108 deletions(-) diff --git a/CodingReadme b/CodingReadme index 88f16ff0a..03de3fc17 100644 --- a/CodingReadme +++ b/CodingReadme @@ -159,6 +159,7 @@ Then with default config setting: cd ~yosys ./yosys -p 'proc; show' tests/simple/fiedler-cooley.v ./yosys -p 'proc; opt; show' tests/simple/fiedler-cooley.v + ./yosys -p 'synth; show' tests/simple/fiedler-cooley.v cd ~yosys make manual diff --git a/manual/CHAPTER_Appnotes.tex b/manual/CHAPTER_Appnotes.tex index 959aabd21..2abfa85da 100644 --- a/manual/CHAPTER_Appnotes.tex +++ b/manual/CHAPTER_Appnotes.tex @@ -2,11 +2,24 @@ \chapter{Application Notes} \label{chapter:appnotes} -\begin{fixme} -This appendix will cover some typical use-cases of Yosys in the form of application notes. -\end{fixme} +% \begin{fixme} +% This appendix will cover some typical use-cases of Yosys in the form of application notes. +% \end{fixme} +% +% \section{Synthesizing using a Cell Library in Liberty Format} +% \section{Reverse Engeneering the MOS6502 from an NMOS Transistor Netlist} +% \section{Reconfigurable Coarse-Grain Synthesis using Intersynth} -\section{Synthesizing using a Cell Library in Liberty Format} -\section{Reverse Engeneering the MOS6502 from an NMOS Transistor Netlist} -\section{Reconfigurable Coarse-Grain Synthesis using Intersynth} +This appendix contains copies of the Yosys application notes. + +\begin{itemize} +\item Yosys AppNote 010: Converting Verilog to BLIF \dotfill Page \pageref{app:010} \hskip2cm\null +\item Yosys AppNote 011: Interactive Design Investigation \dotfill Page \pageref{app:011} \hskip2cm\null +\end{itemize} + +\eject\label{app:010} +\includepdf[pages=-,pagecommand=\thispagestyle{plain}]{APPNOTE_010_Verilog_to_BLIF.pdf} + +\eject\label{app:011} +\includepdf[pages=-,pagecommand=\thispagestyle{plain}]{APPNOTE_011_Design_Investigation.pdf} diff --git a/manual/CHAPTER_Auxprogs.tex b/manual/CHAPTER_Auxprogs.tex index cce3741c2..a00893828 100644 --- a/manual/CHAPTER_Auxprogs.tex +++ b/manual/CHAPTER_Auxprogs.tex @@ -17,3 +17,9 @@ The {\tt yosys-filterlib} tool is a small utility that can be used to strip or extract information from a Liberty file. See Sec.~\ref{sec:techmap_extern} for details. +\section{yosys-abc} + +This is a unmodified copy of ABC \citeweblink{ABC}. Not all versions of Yosys +work with all versions of ABC. So Yosys comes with its own yosys-abc to avoid +compatibility issues between the two. + diff --git a/manual/PRESENTATION_ExAdv.tex b/manual/PRESENTATION_ExAdv.tex index 471516b40..743500918 100644 --- a/manual/PRESENTATION_ExAdv.tex +++ b/manual/PRESENTATION_ExAdv.tex @@ -790,7 +790,7 @@ Unwrap in {\tt test2}: \hfil\begin{tikzpicture} \node at (0,0) {\includegraphics[width=11cm,trim=1.5cm 1.5cm 1.5cm 1.5cm]{PRESENTATION_ExAdv/macc_xilinx_test2d.pdf}}; -\node at (0,-4) {\includegraphics[width=11cm,trim=1.5cm 1.5cm 1.5cm 1.5cm]{PRESENTATION_ExAdv/macc_xilinx_test2e.pdf}}; +\node at (0,-4) {\includegraphics[width=8cm,trim=1.5cm 1.5cm 1.5cm 1.5cm]{PRESENTATION_ExAdv/macc_xilinx_test2e.pdf}}; \node at (1,-1.7) {\begin{lstlisting}[linewidth=5.5cm, frame=single, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys] techmap -map macc_xilinx_unwrap_map.v ;; \end{lstlisting}}; diff --git a/manual/PRESENTATION_ExOth/axis_master.v b/manual/PRESENTATION_ExOth/axis_master.v index 25a1feee4..fe9008adb 100644 --- a/manual/PRESENTATION_ExOth/axis_master.v +++ b/manual/PRESENTATION_ExOth/axis_master.v @@ -13,7 +13,7 @@ module axis_master(aclk, aresetn, tvalid, tready, tdata); if (tvalid && tready) tvalid <= 0; if (!tvalid || !tready) begin - // ^- should be not inverted! + // ^- should not be inverted! state = state ^ state << 13; state = state ^ state >> 7; state = state ^ state << 17; diff --git a/manual/PRESENTATION_ExSyn.tex b/manual/PRESENTATION_ExSyn.tex index 803982295..f0dd96e38 100644 --- a/manual/PRESENTATION_ExSyn.tex +++ b/manual/PRESENTATION_ExSyn.tex @@ -268,7 +268,7 @@ memory -nomap; techmap -map my_memory_map.v; memory_map \end{frame} \begin{frame}[t, fragile]{\subsecname{} -- Example 1/2} -\vbox to 0cm{\includegraphics[width=\linewidth,trim=0cm 0cm 0cm -10cm]{PRESENTATION_ExSyn/memory_01.pdf}\vss} +\vbox to 0cm{\includegraphics[width=\linewidth,trim=0cm 0cm 0cm -6cm]{PRESENTATION_ExSyn/memory_01.pdf}\vss} \vskip-1cm \begin{columns} \column[t]{5cm} @@ -455,7 +455,7 @@ read_verilog -D WITH_MULT cpu_alu.v hierarchy -check -top cpu_top # high-level synthesis -proc; opt; memory -nomap;; fsm; opt +proc; opt; fsm;; memory -nomap; opt # substitute block rams techmap -map map_rams.v @@ -497,7 +497,7 @@ the next part (Section 3, ``Advanced Synthesis'') of this presentation.} \item Yosys provides commands for each phase of the synthesis. \item Each command solves a (more or less) simple problem. \item Complex commands are often only front-ends to simple commands. -\item {\tt proc; opt; memory; opt; fsm; opt; techmap; opt; abc;;} +\item {\tt proc; opt; fsm; opt; memory; opt; techmap; opt; abc;;} \end{itemize} \bigskip diff --git a/manual/PRESENTATION_Intro.tex b/manual/PRESENTATION_Intro.tex index 7697266de..ed600a3e1 100644 --- a/manual/PRESENTATION_Intro.tex +++ b/manual/PRESENTATION_Intro.tex @@ -277,7 +277,7 @@ Direct link to the files: \\ \footnotesize \medskip {\color{YosysGreen}\# the high-level stuff}\\ -\boxalert<3>{proc}; \boxalert<4>{opt}; \boxalert<5>{memory}; \boxalert<6>{opt}; \boxalert<7>{fsm}; \boxalert<8>{opt} +\boxalert<3>{proc}; \boxalert<4>{opt}; \boxalert<5>{fsm}; \boxalert<6>{opt}; \boxalert<7>{memory}; \boxalert<8>{opt} \medskip {\color{YosysGreen}\# mapping to internal cell library}\\ @@ -308,9 +308,9 @@ Direct link to the files: \\ \footnotesize \only<2>{hierarchy -check -top counter}% \only<3>{proc}% \only<4>{opt}% -\only<5>{memory}% +\only<5>{fsm}% \only<6>{opt}% -\only<7>{fsm}% +\only<7>{memory}% \only<8>{opt}% \only<9>{techmap}% \only<10>{opt}% @@ -333,13 +333,13 @@ Direct link to the files: \\ \footnotesize Perform some basic optimizations and cleanups. }% \only<5>{ - Analyze memories and create circuits to implement them. + Analyze and optimize finite state machines. }% \only<6>{ Perform some basic optimizations and cleanups. }% \only<7>{ - Analyze and optimize finite state machines. + Analyze memories and create circuits to implement them. }% \only<8>{ Perform some basic optimizations and cleanups. @@ -398,7 +398,7 @@ hierarchy -check -top counter \begin{frame}[t, fragile]{\subsecname{} -- Step 2/4} \begin{verbatim} -proc; opt; memory; opt; fsm; opt +proc; opt; fsm; opt; memory; opt \end{verbatim} \vfill @@ -427,6 +427,48 @@ clean %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{The synth command} + +\begin{frame}[fragile]{\subsecname{}} +Yosys contains a default (recommended example) synthesis script in form of the +{\tt synth} command. The following commands are executed by this synthesis command: + +\begin{columns} +\column[t]{5cm} +\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys] +begin: + hierarchy -check [-top ] + +coarse: + proc + opt + wreduce + alumacc + share + opt + fsm + opt -fast + memory -nomap + opt_clean +\end{lstlisting} +\column[t]{5cm} +\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys] +fine: + opt -fast -full + memory_map + opt -full + techmap + opt -fast + +abc: + abc -fast + opt -fast +\end{lstlisting} +\end{columns} +\end{frame} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + \subsection{Yosys Commands} \begin{frame}[fragile]{\subsecname{} 1/3 \hspace{0pt plus 1 filll} (excerpt)} @@ -500,6 +542,7 @@ Commands for writing the results: \bigskip Script-Commands for standard synthesis tasks: \begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys] + synth # generic synthesis script synth_xilinx # synthesis for Xilinx FPGAs \end{lstlisting} @@ -603,12 +646,8 @@ endmodule \begin{frame}{\subsecname} \begin{itemize} -\item Multi-dimensional arrays (memories) -\item Writing to arrays using bit- and part-selects (todo for 0.4.0) -\item The wor/wand wire types (maybe for 0.4.0) \item Tri-state logic - -\bigskip +\item The wor/wand wire types (maybe for 0.5) \item Latched logic (is synthesized as logic with feedback loops) \item Some non-synthesizable features that should be ignored in synthesis are not supported by the parser and cause a parser error (file a bug report if you encounter this problem) \end{itemize} @@ -813,10 +852,12 @@ control logic because it is simpler than setting up a commercial flow. \item When building on other Linux distributions: \begin{itemize} \item Needs compiler with some C++11 support +\item See README file for build instructions \item Post to the subreddit if you get stuck \end{itemize} \item Ported to OS X (Darwin) and OpenBSD -\item No win32 support (yet) +\item Native win32 build with VisualStudio +\item Cross win32 build with MXE \end{itemize} \end{frame} diff --git a/manual/PRESENTATION_Prog.tex b/manual/PRESENTATION_Prog.tex index 590451be0..d40024588 100644 --- a/manual/PRESENTATION_Prog.tex +++ b/manual/PRESENTATION_Prog.tex @@ -89,12 +89,13 @@ left with a much simpler version of RTLIL: \bigskip Many commands simply choose to only work on this simpler version: \begin{lstlisting}[xleftmargin=0.5cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont] -if (module->processes.size() != 0 || module->memories.size() != 0) - log_error("This command does not operate on modules with processes " - "and/or memories! Run 'proc' and 'memory' first.\n"); +for (RTLIL::Module *module : design->selected_modules() { + if (module->has_memories_warn() || module->has_processes_warn()) + continue; + .... +} \end{lstlisting} -\bigskip For simplicity we only discuss this version of RTLIL in this presentation. \end{frame} @@ -145,7 +146,9 @@ See {\tt yosys/kernel/rtlil.h} for details. \subsubsection{RTLIL::IdString} \begin{frame}{\subsubsecname}{} -{\tt RTLIL::IdString} is a simple wrapper for {\tt std::string}. It is used for names of RTLIL objects. +{\tt RTLIL::IdString} in many ways behave like a {\tt std::string}. It is used +for names of RTLIL objects. Internally a RTLIL::IdString object is only a +single integer. \medskip The first character of a {\tt RTLIL::IdString} specifies if the name is {\it public\/} or {\it private\/}: @@ -168,25 +171,25 @@ Use the {\tt NEW\_ID} macro to create a new unique private name. \begin{frame}[t, fragile]{\subsubsecname} The {\tt RTLIL::Design} and {\tt RTLIL::Module} structs are the top-level RTLIL -data structures. - -Yosys always operates on one active design, but can hold many designs in memory. +data structures. Yosys always operates on one active design, but can hold many designs in memory. \bigskip \begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++] struct RTLIL::Design { - std::map modules; + std::map modules_; ... }; struct RTLIL::Module { RTLIL::IdString name; - std::map wires; - std::map cells; - std::vector connections; + std::map wires_; + std::map cells_; + std::vector connections_; ... }; \end{lstlisting} + +(Use the various accessor functions instead of directly working with the {\tt *\_} members.) \end{frame} \subsubsection{The RTLIL::Wire Structure} @@ -251,21 +254,22 @@ constants are part of the RTLIL representation itself. \begin{frame}[t, fragile]{\subsubsecname} The {\tt RTLIL::SigSpec} struct represents a signal vector. Each bit can either be a bit from a wire -or a constant value. Consecutive bits from a wire or consecutive constant bits are consolidated into -a {\tt RTLIL::SigChunk}: +or a constant value. \bigskip \begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++] -struct RTLIL::SigChunk { +struct RTLIL::SigBit +{ RTLIL::Wire *wire; - RTLIL::Const data; // only used if wire == NULL - int width, offset; + union { + RTLIL::State data; // used if wire == NULL + int offset; // used if wire != NULL + }; ... }; struct RTLIL::SigSpec { - std::vector chunks; // LSB at index 0 - int width; + std::vector bits_; // LSB at index 0 ... }; \end{lstlisting} @@ -289,7 +293,7 @@ instances: \begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++] struct RTLIL::Cell { RTLIL::IdString name, type; - std::map connections; + std::map connections_; std::map parameters; ... }; @@ -345,7 +349,7 @@ typedef std::pair RTLIL::SigSig; struct RTLIL::Module { ... - std::vector connections; + std::vector connections_; ... }; \end{lstlisting} @@ -354,8 +358,8 @@ struct RTLIL::Module { {\tt RTLIL::SigSig::first} is the driven signal and {\tt RTLIL::SigSig::second} is the driving signal. Example usage (setting wire {\tt foo} to value {\tt 42}): \begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++] -module->connections.push_back(RTLIL::SigSig(module->wires.at("\\foo"), - RTLIL::SigSpec(42, module->wires.at("\\foo")->width))); +module->connect(module->wire("\\foo"), + RTLIL::SigSpec(42, module->wire("\\foo")->width)); \end{lstlisting} \end{frame} @@ -378,17 +382,19 @@ endmodule RTLIL::Module *module = new RTLIL::Module; module->name = "\\absval"; -RTLIL::Wire *a = module->new_wire(4, "\\a"); +RTLIL::Wire *a = module->addWire("\\a", 4); a->port_input = true; a->port_id = 1; -RTLIL::Wire *y = module->new_wire(4, "\\y"); +RTLIL::Wire *y = module->addWire("\\y", 4); y->port_output = true; y->port_id = 2; -RTLIL::Wire *a_inv = module->new_wire(4, NEW_ID); +RTLIL::Wire *a_inv = module->addWire(NEW_ID, 4); module->addNeg(NEW_ID, a, a_inv, true); module->addMux(NEW_ID, a, a_inv, RTLIL::SigSpec(a, 1, 3), y); + +module->fixup_ports(); \end{lstlisting} \end{frame} @@ -431,8 +437,8 @@ In this case {\tt a}, {\tt x}, and {\tt y} are all different names for the same \smallskip \begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++] -RTLIL::SigSpec a(module->wires.at("\\a")), x(module->wires.at("\\x")), - y(module->wires.at("\\y")); +RTLIL::SigSpec a(module->wire("\\a")), x(module->wire("\\x")), + y(module->wire("\\y")); log("%d %d %d\n", a == x, x == y, y == a); // will print "0 0 0" \end{lstlisting} @@ -462,9 +468,9 @@ log("Mapped signal x: %s\n", log_signal(sigmap(x))); \end{lstlisting} \medskip -Use {\tt RTLIL::id2cstr()} to create a C-string for an {\tt RTLIL::IdString}: +Use {\tt log\_id()} to create a C-string for an {\tt RTLIL::IdString}: \begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++] -log("Name of this module: %s\n", RTLIL::id2cstr(module->name)); +log("Name of this module: %s\n", log_id(module->name)); \end{lstlisting} \medskip @@ -513,9 +519,8 @@ a new yosys command: \bigskip \begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++] -#include "kernel/rtlil.h" -#include "kernel/register.h" -#include "kernel/log.h" +#include "kernel/yosys.h" +USING_YOSYS_NAMESPACE struct MyPass : public Pass { MyPass() : Pass("my_cmd", "just a simple test") { } @@ -526,9 +531,9 @@ struct MyPass : public Pass { log(" %s\n", arg.c_str()); log("Modules in current design:\n"); - for (auto &mod : design->modules) - log(" %s (%zd wires, %zd cells)\n", RTLIL::id2cstr(mod.first), - mod.second->wires.size(), mod.second->cells.size()); + for (auto mod : design->modules()) + log(" %s (%d wires, %d cells)\n", log_id(mod), + GetSize(mod->wires), GetSize(mod->cells)); } } MyPass; \end{lstlisting} @@ -566,7 +571,7 @@ yosys -m ./my_cmd.so -p 'my_cmd foo bar' \item \dots and even simpler if you don't need RTLIL::Memory or RTLIL::Process objects. \bigskip -\item Writing synthesis software? Consider learning the Yosys API and make your stuff +\item Writing synthesis software? Consider learning the Yosys API and make your work part of the Yosys framework. \end{itemize} diff --git a/manual/PRESENTATION_Prog/my_cmd.cc b/manual/PRESENTATION_Prog/my_cmd.cc index 3e3cf13a0..1d28ce974 100644 --- a/manual/PRESENTATION_Prog/my_cmd.cc +++ b/manual/PRESENTATION_Prog/my_cmd.cc @@ -1,6 +1,9 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + struct MyPass : public Pass { MyPass() : Pass("my_cmd", "just a simple test") { } virtual void execute(std::vector args, RTLIL::Design *design) @@ -25,6 +28,7 @@ struct Test1Pass : public Pass { log_error("A module with the name absval already exists!\n"); RTLIL::Module *module = design->addModule("\\absval"); + log("Name of this module: %s\n", log_id(module)); RTLIL::Wire *a = module->addWire("\\a", 4); a->port_input = true; @@ -38,7 +42,7 @@ struct Test1Pass : public Pass { module->addNeg(NEW_ID, a, a_inv, true); module->addMux(NEW_ID, a, a_inv, RTLIL::SigSpec(a, 3), y); - log("Name of this module: %s\n", log_id(module)); + module->fixup_ports(); } } Test1Pass; @@ -69,3 +73,4 @@ struct Test2Pass : public Pass { } } Test2Pass; +PRIVATE_NAMESPACE_END diff --git a/manual/command-reference-manual.tex b/manual/command-reference-manual.tex index 35249ed88..697add159 100644 --- a/manual/command-reference-manual.tex +++ b/manual/command-reference-manual.tex @@ -15,22 +15,88 @@ library to a target architecture. -script use the specified ABC script file instead of the default script. + if starts with a plus sign (+), then the rest of the filename + string is interprated as the command string to be passed to ABC. the + leading plus sign is removed and all commas (,) in the string are + replaced with blanks before the string is passed to ABC. + + if no -script parameter is given, the following scripts are used: + + for -liberty without -constr: + strash; scorr -v; ifraig -v; retime -v {D}; strash; dch -vf; + map -v {D} + + for -liberty with -constr: + strash; scorr -v; ifraig -v; retime -v {D}; strash; dch -vf; + map -v {D}; buffer -v; upsize -v {D}; dnsize -v {D}; + stime -p + + for -lut: + strash; scorr -v; ifraig -v; retime -v; strash; dch -vf; if -v + + otherwise: + strash; scorr -v; ifraig -v; retime -v; strash; dch -vf; map -v + + -fast + use different default scripts that are slightly faster (at the cost + of output quality): + + for -liberty without -constr: + retime -v {D}; map -v {D} + + for -liberty with -constr: + retime -v {D}; map -v {D}; buffer -v; upsize -v {D}; + dnsize -v {D}; stime -p + + for -lut: + retime -v; if -v + + otherwise: + retime -v; map -v + -liberty generate netlists for the specified cell library (using the liberty - file format). Without this option, ABC is used to optimize the netlist - but keeps using yosys's internal gate library. This option is ignored if - the -script option is also used. + file format). -constr - pass this file with timing constraints to ABC + pass this file with timing constraints to ABC. use with -liberty. + + a constr file contains two lines: + set_driving_cell + set_load + + the set_driving_cell statement defines which cell type is assumed to + drive the primary inputs and the set_load statement sets the load in + femtofarads for each primary output. + + -D + set delay target. the string {D} in the default scripts above is + replaced by this option when used, and an empty string otherwise. -lut generate netlist using luts of (max) the specified width. + -dff + also pass $_DFF_?_ cells through ABC (only one clock domain, if many + clock domains are present in a module, the one with the largest number + of $_DFF_?_ cells in it is used) + + -clk [!] + use the specified clock domain. (when this option is used in combination + with -dff, then it falls back to the automatic dection of clock domain + if the specified clock is not found in a module.) + + -keepff + set the "keep" attribute on flip-flop output wires. (and thus preserve + them, for example for equivialence checking.) + -nocleanup when this option is used, the temporary files created by this pass are not removed. this is useful for debugging. +When neither -liberty nor -lut is used, the Yosys standard cell library is +loaded into ABC before the ABC script is executed. + This pass does not operate on modules with unprocessed processes in it. (I.e. the 'proc' pass should be used first to convert processes to netlists.) @@ -59,6 +125,15 @@ Like 'add -input', but also connect the signal between instances of the selected modules. \end{lstlisting} +\section{alumacc -- extract ALU and MACC cells} +\label{cmd:alumacc} +\begin{lstlisting}[numbers=left,frame=single] + alumacc [selection] + +This pass translates arithmetic operations $add, $mul, $lt, etc. to $alu and +$macc cells. +\end{lstlisting} + \section{cd -- a shortcut for 'select -module '} \label{cmd:cd} \begin{lstlisting}[numbers=left,frame=single] @@ -92,6 +167,129 @@ When commands are separated using the ';;;' token, this command will be executed in -purge mode between the commands. \end{lstlisting} +\section{connect -- create or remove connections} +\label{cmd:connect} +\begin{lstlisting}[numbers=left,frame=single] + connect [-nomap] [-nounset] -set + +Create a connection. This is equivialent to adding the statement 'assign + = ;' to the verilog input. Per default, all existing +drivers for are unconnected. This can be overwritten by using +the -nounset option. + + + connect [-nomap] -unset + +Unconnect all existing drivers for the specified expression. + + + connect [-nomap] -port + +Connect the specified cell port to the specified cell port. + + +Per default signal alias names are resolved and all signal names are mapped +the the signal name of the primary driver. Using the -nomap option deactivates +this behavior. + +The connect command operates in one module only. Either only one module must +be selected or an active module must be set using the 'cd' command. + +This command does not operate on module with processes. +\end{lstlisting} + +\section{connwrappers -- replace undef values with defined constants} +\label{cmd:connwrappers} +\begin{lstlisting}[numbers=left,frame=single] + connwrappers [options] [selection] + +Wrappers are used in coarse-grain synthesis to wrap cells with smaller ports +in wrapper cells with a (larger) constant port size. I.e. the upper bits +of the wrapper outut are signed/unsigned bit extended. This command uses this +knowlege to rewire the inputs of the driven cells to match the output of +the driving cell. + + -signed + -unsigned + consider the specified signed/unsigned wrapper output + + -port + use the specified parameter to decide if signed or unsigned + +The options -signed, -unsigned, and -port can be specified multiple times. +\end{lstlisting} + +\section{copy -- copy modules in the design} +\label{cmd:copy} +\begin{lstlisting}[numbers=left,frame=single] + copy old_name new_name + +Copy the specified module. Note that selection patterns are not supported +by this command. +\end{lstlisting} + +\section{cover -- print code coverage counters} +\label{cmd:cover} +\begin{lstlisting}[numbers=left,frame=single] + cover [options] [pattern] + +Print the code coverage counters collected using the cover() macro in the Yosys +C++ code. This is useful to figure out what parts of Yosys are utilized by a +test bench. + + -q + Do not print output to the normal destination (console and/or log file) + + -o file + Write output to this file, truncate if exists. + + -a file + Write output to this file, append if exists. + + -d dir + Write output to a newly created file in the specified directory. + +When one or more pattern (shell wildcards) are specified, then only counters +matching at least one pattern are printed. + + +It is also possible to instruct Yosys to print the coverage counters on program +exit to a file using environment variables: + + YOSYS_COVER_DIR="{dir-name}" yosys {args} + + This will create a file (with an auto-generated name) in this + directory and write the coverage counters to it. + + YOSYS_COVER_FILE="{file-name}" yosys {args} + + This will append the coverage counters to the specified file. + + +Hint: Use the following AWK command to consolidate Yosys coverage files: + + gawk '{ p[$3] = $1; c[$3] += $2; } END { for (i in p) + printf "%-60s %10d %s\n", p[i], c[i], i; }' {files} | sort -k3 + + +Coverage counters are only available in debug builds of Yosys for Linux. +\end{lstlisting} + +\section{delete -- delete objects in the design} +\label{cmd:delete} +\begin{lstlisting}[numbers=left,frame=single] + delete [selection] + +Deletes the selected objects. This will also remove entire modules, if the +whole module is selected. + + + delete {-input|-output|-port} [selection] + +Does not delete any object but removes the input and/or output flag on the +selected wires, thus 'deleting' module ports. +\end{lstlisting} + \section{design -- save, restore and reset current design} \label{cmd:design} \begin{lstlisting}[numbers=left,frame=single] @@ -105,10 +303,36 @@ Clear the current design. Save the current design under the given name. + design -stash + +Save the current design under the given name and then clear the current design. + + + design -push + +Push the current design to the stack and then clear the current design. + + + design -pop + +Reset the current design and pop the last design from the stack. + + design -load Reset the current design and load the design previously saved under the given name. + + + design -copy-from [-as ] + +Copy modules from the specified design into the current one. The selection is +evaluated in the other design. + + + design -copy-to [-as ] [selection] + +Copy modules from the current design into the soecified one. \end{lstlisting} \section{dfflibmap -- technology mapping of flip-flops} @@ -139,7 +363,23 @@ ilang format. only dump the module headers if the entire module is selected -outfile - Write to the specified file. + write to the specified file. + + -append + like -outfile but append instead of overwrite +\end{lstlisting} + +\section{echo -- turning echoing back of commands on and off} +\label{cmd:echo} +\begin{lstlisting}[numbers=left,frame=single] + echo on + +Print all commands to log before executing them. + + + echo off + +Do not print all commands to log before executing them. (default) \end{lstlisting} \section{eval -- evaluate the circuit given an input} @@ -164,6 +404,38 @@ inputs. then all output ports of the current module are used. \end{lstlisting} +\section{expose -- convert internal signals to module ports} +\label{cmd:expose} +\begin{lstlisting}[numbers=left,frame=single] + expose [options] [selection] + +This command exposes all selected internal signals of a module as additional +outputs. + + -dff + only consider wires that are directly driven by register cell. + + -cut + when exposing a wire, create an input/output pair and cut the internal + signal path at that wire. + + -shared + only expose those signals that are shared ammong the selected modules. + this is useful for preparing modules for equivialence checking. + + -evert + also turn connections to instances of other modules to additional + inputs and outputs and remove the module instances. + + -evert-dff + turn flip-flops to sets of inputs and outputs. + + -sep + when creating new wire/port names, the original object name is suffixed + with this separator (default: '.') and the port name or a type + designator for the exposed signal. +\end{lstlisting} + \section{extract -- find subcircuits and replace them with cells} \label{cmd:extract} \begin{lstlisting}[numbers=left,frame=single] @@ -175,7 +447,12 @@ in the given map file and replaces them with instances of this modules. The map file can be a verilog source file (*.v) or an ilang file (*.il). -map - use the modules in this file as reference + use the modules in this file as reference. This option can be used + multiple times. + + -map % + use the modules in this in-memory design as reference. This option can + be used multiple times. -verbose print debug output while analyzing @@ -209,6 +486,12 @@ map file can be a verilog source file (*.v) or an ilang file (*.il). -wire_attr Attributes on wires with the given name must match. + -ignore_parameters + Do not use parameters when matching cells. + + -ignore_param + Do not use this parameter when matching cells. + This pass does not operate on modules with uprocessed processes in it. (I.e. the 'proc' pass should be used first to convert processes to netlists.) @@ -257,11 +540,27 @@ pass is using the current design as mapping library. This pass performs functional reduction in the circuit. I.e. if two nodes are equivialent, they are merged to one node and one of the redundant drivers is -removed. +disconnected. A subsequent call to 'clean' will remove the redundant drivers. - -try - do not issue an error when the analysis fails. - (usually beacause of logic loops in the design) + -v, -vv + enable verbose or very verbose output + + -inv + enable explicit handling of inverted signals + + -stop + stop after reduction operations. this is mostly used for + debugging the freduce command itself. + + -dump + dump the design to __.il after each reduction + operation. this is mostly used for debugging the freduce command. + +This pass is undef-aware, i.e. it considers don't-care values for detecting +equivialent nodes. + +All selected wires are considered for rewiring. The selected cells cover the +circuit that is analyzed. \end{lstlisting} \section{fsm -- extract and optimize finite state machines} @@ -428,10 +727,24 @@ needed. also check the design hierarchy. this generates an error when an unknown module is used as cell type. + -purge_lib + by default the hierarchy command will not remove library (blackbox) + module. use this options to also remove unused blackbox modules. + + -libdir + search for files named .v in the specified directory + for unknown modules and automatically run read_verilog for each + unknown module. + -keep_positionals per default this pass also converts positional arguments in cells to arguments using port names. this option disables this behavior. + -nokeep_asserts + per default this pass sets the "keep" attribute on all modules + that directly or indirectly contain one or more $assert cells. this + option disables this behavior. + -top use the specified top module to built a design hierarchy. modules outside this tree (unused modules) are removed. @@ -457,6 +770,25 @@ This pass ignores the current selection and always operates on all modules in the current design. \end{lstlisting} +\section{hilomap -- technology mapping of constant hi- and/or lo-drivers} +\label{cmd:hilomap} +\begin{lstlisting}[numbers=left,frame=single] + hilomap [options] [selection] + +Map constants to 'tielo' and 'tiehi' driver cells. + + -hicell + Replace constant hi bits with this cell. + + -locell + Replace constant lo bits with this cell. + + -singleton + Create only one hi/lo cell and connect all constant bits + to that cell. Per default a separate cell is created for + each constant bit. +\end{lstlisting} + \section{history -- show last interactive commands} \label{cmd:history} \begin{lstlisting}[numbers=left,frame=single] @@ -491,6 +823,35 @@ the resulting cells to more sophisticated PAD cells. -nameparam Use the specified parameter to set the port name. + + -bits + create individual bit-wide buffers even for ports that + are wider. (the default behavio is to create word-wide + buffers use -widthparam to set the word size on the cell.) +\end{lstlisting} + +\section{log -- print text and log files} +\label{cmd:log} +\begin{lstlisting}[numbers=left,frame=single] + log string + +Print the given string to the screen and/or the log file. This is useful for TCL +scripts, because the TCL command "puts" only goes to stdout but not to +logfiles. + + -stdout + Print the output to stdout too. This is useful when all Yosys is executed + with a script and the -q (quiet operation) argument to notify the user. + + -stderr + Print the output to stderr too. + + -nolog + Don't use the internal log() command. Use either -stdout or -stderr, + otherwise no output will be generated at all. + + -n + do not append a newline \end{lstlisting} \section{ls -- list modules or objects in modules} @@ -509,6 +870,15 @@ on the whole design or whole active module. Use 'select -list' to show a list of currently selected objects. \end{lstlisting} +\section{maccmap -- mapping macc cells} +\label{cmd:maccmap} +\begin{lstlisting}[numbers=left,frame=single] + maccmap [-unmap] [selection] + +This pass maps $macc cells to yosys gate primitives. When the -unmap option is +used then the $macc cell is mapped to $and, $sub, etc. cells instead. +\end{lstlisting} + \section{memory -- translate memories to basic cells} \label{cmd:memory} \begin{lstlisting}[numbers=left,frame=single] @@ -517,6 +887,9 @@ of currently selected objects. This pass calls all the other memory_* passes in a useful order: memory_dff + opt_clean + memory_share + opt_clean memory_collect memory_map (skipped if called with -nomap) @@ -536,11 +909,14 @@ memory cells. \section{memory\_dff -- merge input/output DFFs into memories} \label{cmd:memory_dff} \begin{lstlisting}[numbers=left,frame=single] - memory_dff [selection] + memory_dff [options] [selection] This pass detects DFFs at memory ports and merges them into the memory port. I.e. it consumes an asynchronous memory port and the flip-flops at its interface and yields a synchronous memory port. + + -wr_only + do not merge registers on read ports \end{lstlisting} \section{memory\_map -- translate multiport memories to basic cells} @@ -552,26 +928,101 @@ This pass converts multiport memory cells as generated by the memory_collect pass to word-wide DFFs and address decoders. \end{lstlisting} +\section{memory\_share -- consolidate memory ports} +\label{cmd:memory_share} +\begin{lstlisting}[numbers=left,frame=single] + memory_share [selection] + +This pass merges share-able memory ports into single memory ports. + +The following methods are used to consolidate the number of memory ports: + + - When write ports are connected to async read ports accessing the same + address, then this feedback path is converted to a write port with + byte/part enable signals. + + - When multiple write ports access the same address then this is converted + to a single write port with a more complex data and/or enable logic path. + + - When multiple write ports are never accessed at the same time (a SAT + solver is used to determine this), then the ports are merged into a single + write port. + +Note that in addition to the algorithms implemented in this pass, the $memrd +and $memwr cells are also subject to generic resource sharing passes (and other +optimizations) such as opt_share. +\end{lstlisting} + +\section{memory\_unpack -- unpack multi-port memory cells} +\label{cmd:memory_unpack} +\begin{lstlisting}[numbers=left,frame=single] + memory_unpack [selection] + +This pass converts the multi-port $mem memory cells into individual $memrd and +$memwr cells. It is the counterpart to the memory_collect pass. +\end{lstlisting} + +\section{miter -- automatically create a miter circuit} +\label{cmd:miter} +\begin{lstlisting}[numbers=left,frame=single] + miter -equiv [options] gold_name gate_name miter_name + +Creates a miter circuit for equivialence checking. The gold- and gate- modules +must have the same interfaces. The miter circuit will have all inputs of the +two source modules, prefixed with 'in_'. The miter circuit has a 'trigger' +output that goes high if an output mismatch between the two source modules is +detected. + + -ignore_gold_x + a undef (x) bit in the gold module output will match any value in + the gate module output. + + -make_outputs + also route the gold- and gate-outputs to 'gold_*' and 'gate_*' outputs + on the miter circuit. + + -make_outcmp + also create a cmp_* output for each gold/gate output pair. + + -make_assert + also create an 'assert' cell that checks if trigger is always low. + + -flatten + call 'flatten; opt_const -keepdc -undriven;;' on the miter circuit. +\end{lstlisting} + \section{opt -- perform simple optimizations} \label{cmd:opt} \begin{lstlisting}[numbers=left,frame=single] - opt [selection] + opt [options] [selection] This pass calls all the other opt_* passes in a useful order. This performs a series of trivial optimizations and cleanups. This pass executes the other passes in the following order: - opt_const + opt_const [-mux_undef] [-mux_bool] [-undriven] [-fine] [-full] [-keepdc] opt_share -nomux do opt_muxtree - opt_reduce + opt_reduce [-fine] [-full] opt_share opt_rmdff - opt_clean - opt_const - while [changed design] + opt_clean [-purge] + opt_const [-mux_undef] [-mux_bool] [-undriven] [-fine] [-full] [-keepdc] + while + +When called with -fast the following script is used instead: + + do + opt_const [-mux_undef] [-mux_bool] [-undriven] [-fine] [-full] [-keepdc] + opt_share + opt_rmdff + opt_clean [-purge] + while + +Note: Options in square brackets (such as [-keepdc]) are passed through to +the opt_* commands when given to 'opt'. \end{lstlisting} \section{opt\_clean -- remove unused cells and wires} @@ -593,9 +1044,30 @@ This pass only operates on completely selected modules without processes. \section{opt\_const -- perform const folding} \label{cmd:opt_const} \begin{lstlisting}[numbers=left,frame=single] - opt_const [selection] + opt_const [options] [selection] This pass performs const folding on internal cell types with constant inputs. + + -mux_undef + remove 'undef' inputs from $mux, $pmux and $_MUX_ cells + + -mux_bool + replace $mux cells with inverters or buffers when possible + + -undriven + replace undriven nets with undef (x) constants + + -fine + perform fine-grain optimizations + + -full + alias for -mux_undef -mux_bool -undriven -fine + + -keepdc + some optimizations change the behavior of the circuit with respect to + don't-care bits. for example in 'a+0' a single x-bit in 'a' will cause + all result bits to be set to x. this behavior changes when 'a+0' is + replaced by 'a'. the -keepdc option disables all such optimizations. \end{lstlisting} \section{opt\_muxtree -- eliminate dead trees in multiplexer trees} @@ -613,7 +1085,7 @@ This pass only operates on completely selected modules without processes. \section{opt\_reduce -- simplify large MUXes and AND/OR gates} \label{cmd:opt_reduce} \begin{lstlisting}[numbers=left,frame=single] - opt_reduce [selection] + opt_reduce [options] [selection] This pass performs two interlinked optimizations: @@ -622,6 +1094,12 @@ duplicated inputs. 2. it identifies duplicated inputs to MUXes and replaces them with a single input with the original control signals OR'ed together. + + -fine + perform fine-grain optimizations + + -full + alias for -fine \end{lstlisting} \section{opt\_rmdff -- remove DFFs with constant inputs} @@ -645,6 +1123,23 @@ are then merged to one cell. Do not merge MUX cells. \end{lstlisting} +\section{plugin -- load and list loaded plugins} +\label{cmd:plugin} +\begin{lstlisting}[numbers=left,frame=single] + plugin [options] + +Load and list loaded plugins. + + -i + Load (install) the specified plugin. + + -a + Register the specified alias name for the loaded plugin + + -l + List loaded plugins +\end{lstlisting} + \section{proc -- translate processes to netlists} \label{cmd:proc} \begin{lstlisting}[numbers=left,frame=single] @@ -739,14 +1234,43 @@ Load modules from an ilang file to the current design. (ilang is a text representation of a design in yosys's internal format.) \end{lstlisting} +\section{read\_liberty -- read cells from liberty file} +\label{cmd:read_liberty} +\begin{lstlisting}[numbers=left,frame=single] + read_liberty [filename] + +Read cells from liberty file as modules into current design. + + -lib + only create empty blackbox modules + + -ignore_redef + ignore re-definitions of modules. (the default behavior is to + create an error message.) + + -ignore_miss_func + ignore cells with missing function specification of outputs + + -ignore_miss_dir + ignore cells with a missing or invalid direction + specification on a pin + + -setattr + set the specified attribute (to the value 1) on all loaded modules +\end{lstlisting} + \section{read\_verilog -- read modules from verilog file} \label{cmd:read_verilog} \begin{lstlisting}[numbers=left,frame=single] - read_verilog [filename] + read_verilog [options] [filename] Load modules from a verilog file to the current design. A large subset of Verilog-2005 is supported. + -sv + enable support for SystemVerilog features. (only a small subset + of SystemVerilog is supported) + -dump_ast1 dump abstract syntax tree (before simplification) @@ -794,10 +1318,21 @@ Verilog-2005 is supported. don't perform basic optimizations (such as const folding) in the high-level front-end. + -icells + interpret cell types starting with '$' as internal cell types + -ignore_redef ignore re-definitions of modules. (the default behavior is to create an error message.) + -defer + only read the abstract syntax tree and defer actual compilation + to a later 'hierarchy' command. Useful in cases where the default + parameters of modules yield invalid or not synthesizable code. + + -setattr + set the specified attribute (to the value 1) on all loaded modules + -Dname[=definition] define the preprocessor symbol 'name' and set its optional value 'definition' @@ -805,6 +1340,14 @@ Verilog-2005 is supported. -Idir add 'dir' to the directories which are used when searching include files + +The command 'verilog_defaults' can be used to register default options for +subsequent calls to 'read_verilog'. + +Note that the Verilog frontend does a pretty good job of processing valid +verilog input, but has not very good error reporting. It generally is +recommended to use a simulator (for example icarus verilog) for checking +the syntax of the code, rather than to rely on read_verilog for that. \end{lstlisting} \section{rename -- rename object in the design} @@ -816,10 +1359,17 @@ Rename the specified object. Note that selection patterns are not supported by this command. - rename -enumerate [selection] + rename -enumerate [-pattern ] [selection] Assign short auto-generated names to all selected wires and cells with private -names. +names. The -pattern option can be used to set the pattern for the new names. +The character % in the pattern is replaced with a integer number. The default +pattern is '_%_'. + + rename -hide [selection] + +Assign private names (the ones with $-prefix) to all selected wires and cells +with public names. This ignores all selected ports. \end{lstlisting} \section{sat -- solve a SAT problem in the circuit} @@ -864,9 +1414,15 @@ and additional constraints passed as parameters. show the model for the specified signal. if no -show option is passed then a set of signals to be shown is automatically selected. + -show-inputs, -show-outputs + add all module input (output) ports to the list of shown signals + -ignore_div_by_zero ignore all solutions that involve a division by zero + -ignore_unknown_cells + ignore all cells that can not be matched to a SAT model + The following options can be used to set up a sequential problem: -seq @@ -889,21 +1445,50 @@ The following options can be used to set up a sequential problem: -set-init-undef set all initial states (not set using -set-init) to undef + -set-init-def + do not force a value for the initial state but do not allow undef + + -set-init-zero + set all initial states (not set using -set-init) to zero + + -dump_vcd + dump SAT model (counter example in proof) to VCD file + + -dump_cnf + dump CNF of SAT problem (in DIMACS format). in temporal induction + proofs this is the CNF of the first induction step. + The following additional options can be used to set up a proof. If also -seq is passed, a temporal induction proof is performed. + -tempinduct + Perform a temporal induction proof. In a temporalinduction proof it is + proven that the condition holds forever after the number of time steps + specified using -seq. + + -tempinduct-def + Perform a temporal induction proof. Assume an initial state with all + registers set to defined values for the induction step. + -prove - Attempt to proof that is always . In a temporal - induction proof it is proven that the condition holds forever after - the number of time steps passed using -seq. + Attempt to proof that is always . -prove-x Like -prove, but an undef (x) bit in the lhs matches any value on the right hand side. Useful for equivialence checking. + -prove-asserts + Prove that all asserts in the design hold. + + -prove-skip + Do not enforce the prove-condition for the first time steps. + -maxsteps Set a maximum length for the induction. + -initsteps + Set initial length for the induction. + -timeout Maximum number of seconds a single SAT instance may take. @@ -912,6 +1497,12 @@ is passed, a temporal induction proof is performed. -verify-no-timeout Like -verify but do not return an error for timeouts. + + -falsify + Return an error and stop the synthesis script if the proof succeeds. + + -falsify-no-timeout + Like -falsify but do not return an error for timeouts. \end{lstlisting} \section{scatter -- add additional intermediate nets} @@ -960,15 +1551,24 @@ design. \section{script -- execute commands from script file} \label{cmd:script} \begin{lstlisting}[numbers=left,frame=single] - script + script [:] This command executes the yosys commands in the specified file. + +The 2nd argument can be used to only execute the section of the +file between the specified labels. An empty from label is synonymous +for the beginning of the file and an empty to label is synonymous +for the end of the file. + +If only one label is specified (without ':') then only the block +marked with that label (until the next label) is executed. \end{lstlisting} \section{select -- modify and view the list of selected objects} \label{cmd:select} \begin{lstlisting}[numbers=left,frame=single] select [ -add | -del | -set ] + select [ -assert-none | -assert-any ] select [ -list | -write | -count | -clear ] select -module @@ -987,7 +1587,22 @@ described here. -set do not modify the current selection. instead save the new selection - under the given name (see @ below). + under the given name (see @ below). to save the current selection, + use "select -set %" + + -assert-none + do not modify the current selection. instead assert that the given + selection is empty. i.e. produce an error if any object matching the + selection is found. + + -assert-any + do not modify the current selection. instead assert that the given + selection is non-empty. i.e. produce an error if no object matching + the selection is found. + + -assert-count N + do not modify the current selection. instead assert that the given + selection contains exactly N objects. -list list all objects in the current selection @@ -999,8 +1614,12 @@ described here. count all objects in the current selection -clear - clear the current selection. this effectively selects the - whole design. + clear the current selection. this effectively selects the whole + design. it also resets the selected module (see -module). use the + command 'select *' to select everything but stay in the current module. + + -none + create an empty selection. the current module is unchanged. -module limit the current scope to the specified module. @@ -1030,8 +1649,12 @@ Pushing (selecting) object when in -module mode: select the specified object(s) from the current module -A can be a module name or wildcard expression (*, ?, [..]) -matching module names. +A can be a module name, wildcard expression (*, ?, [..]) +matching module names, or one of the following: + + A:, A:= + all modules with an attribute matching the given pattern + in addition to = also <, <=, >=, and > are supported An can be an object name, wildcard expression, or one of the following: @@ -1039,6 +1662,12 @@ the following: w: all wires with a name matching the given wildcard pattern + i:, o:, x: + all inputs (i:), outputs (o:) or any ports (x:) with matching names + + s:, s:: + all wires with a matching width + m: all memories with a name matching the given pattern @@ -1055,7 +1684,11 @@ the following: all objects with an attribute name matching the given pattern a:= - all objects with a matching attribute name-value-pair + all objects with a matching attribute name-value-pair. + in addition to = also <, <=, >=, and > are supported + + r:, r:= + cells with matching parameters. also with <, <=, >= and >. n: all objects with a name matching the given pattern @@ -1084,6 +1717,12 @@ The following actions can be performed on the top sets on the stack: %d pop the top set from the stack and subtract it from the new top + %D + like %d but swap the roles of two top sets on the stack + + %c + create a copy of the top set rom the stack and push it + %x[|*][.][:[:..]] expand top set num times according to the specified rules. (i.e. select all cells connected to selected wires and select all @@ -1101,12 +1740,96 @@ The following actions can be performed on the top sets on the stack: %co[|*][.][:[:..]] simmilar to %x, but only select input (%ci) or output cones (%co) + %a + expand top set by selecting all wires that are (at least in part) + aliases for selected wires. + + %s + expand top set by adding all modules of instantiated cells in selected + modules + + %m + expand top set by selecting all modules that contain selected objects + Example: the following command selects all wires that are connected to a 'GATE' input of a 'SWITCH' cell: select */t:SWITCH %x:+[GATE] */t:SWITCH %d \end{lstlisting} +\section{setattr -- set/unset attributes on objects} +\label{cmd:setattr} +\begin{lstlisting}[numbers=left,frame=single] + setattr [ -mod ] [ -set name value | -unset name ]... [selection] + +Set/unset the given attributes on the selected objects. String values must be +passed in double quotes ("). + +When called with -mod, this command will set and unset attributes on modules +instead of objects within modules. +\end{lstlisting} + +\section{setparam -- set/unset parameters on objects} +\label{cmd:setparam} +\begin{lstlisting}[numbers=left,frame=single] + setparam [ -set name value | -unset name ]... [selection] + +Set/unset the given parameters on the selected cells. String values must be +passed in double quotes ("). +\end{lstlisting} + +\section{setundef -- replace undef values with defined constants} +\label{cmd:setundef} +\begin{lstlisting}[numbers=left,frame=single] + setundef [options] [selection] + +This command replaced undef (x) constants with defined (0/1) constants. + + -undriven + also set undriven nets to constant values + + -zero + replace with bits cleared (0) + + -one + replace with bits set (1) + + -random + replace with random bits using the specified integer als seed + value for the random number generator. +\end{lstlisting} + +\section{share -- perform sat-based resource sharing} +\label{cmd:share} +\begin{lstlisting}[numbers=left,frame=single] + share [options] [selection] + +This pass merges shareable resources into a single resource. A SAT solver +is used to determine if two resources are share-able. + + -force + Per default the selection of cells that is considered for sharing is + narrowed using a list of cell types. With this option all selected + cells are considered for resource sharing. + + IMPORTANT NOTE: If the -all option is used then no cells with internal + state must be selected! + + -aggressive + Per default some heuristics are used to reduce the number of cells + considered for resource sharing to only large resources. This options + turns this heuristics off, resulting in much more cells being considered + for resource sharing. + + -fast + Only consider the simple part of the control logic in SAT solving, resulting + in much easier SAT problems at the cost of maybe missing some oportunities + for resource sharing. + + -limit N + Only perform the first N merges, then stop. This is useful for debugging. +\end{lstlisting} + \section{shell -- enter interactive command mode} \label{cmd:shell} \begin{lstlisting}[numbers=left,frame=single] @@ -1163,11 +1886,16 @@ to a graphics file (usually SVG or PostScript). -prefix generate .* instead of ~/.yosys_show.* - -color - assign the specified color to the specified wire. The object can be + -color + assign the specified color to the specified object. The object can be a single selection wildcard expressions or a saved set of objects in the @ syntax (see "help select" for details). + -label + assign the specified label text to the specified object. The object can + be a single selection wildcard expressions or a saved set of objects in + the @ syntax (see "help select" for details). + -colors Randomly assign colors to the wires. The integer argument is the seed for the random number generator. Change the seed value if the colored @@ -1176,6 +1904,10 @@ to a graphics file (usually SVG or PostScript). -width annotate busses with a label indicating the width of the bus. + -signed + mark ports (A, B) that are declarted as signed (using the [AB]_SIGNED + cell parameter) with an asterisk next to the port name. + -stretch stretch the graph so all inputs are on the left side and all outputs (including inout ports) are on the right side. @@ -1189,8 +1921,11 @@ to a graphics file (usually SVG or PostScript). -long do not abbeviate objects with internal ($-prefixed) names -When no is specified, SVG is used. When no and is -specified, 'yosys-svgviewer' is used to display the schematic. + -notitle + do not add the module name as graph title to the dot file + +When no is specified, 'dot' is used. When no and is +specified, 'xdot' is used to display the schematic. The generated output files are '~/.yosys_show.dot' and '~/.yosys_show.', unless another prefix is specified using -prefix . @@ -1210,6 +1945,43 @@ primitives. The following internal cell types are mapped by this pass: $sr, $dff, $dffsr, $adff, $dlatch \end{lstlisting} +\section{splice -- create explicit splicing cells} +\label{cmd:splice} +\begin{lstlisting}[numbers=left,frame=single] + splice [options] [selection] + +This command adds $slice and $concat cells to the design to make the splicing +of multi-bit signals explicit. This for example is useful for coarse grain +synthesis, where dedidacted hardware is needed to splice signals. + + -sel_by_cell + only select the cell ports to rewire by the cell. if the selection + contains a cell, than all cell inputs are rewired, if necessary. + + -sel_by_wire + only select the cell ports to rewire by the wire. if the selection + contains a wire, than all cell ports driven by this wire are wired, + if necessary. + + -sel_any_bit + it is sufficient if the driver of any bit of a cell port is selected. + by default all bits must be selected. + + -no_outputs + do not rewire selected module outputs. + + -port + only rewire cell ports with the specified name. can be used multiple + times. implies -no_output. + + -no_port + do not rewire cell ports with the specified name. can be used multiple + times. can not be combined with -port . + +By default selected output wires and all cell ports of selected cells driven +by selected wires are rewired. +\end{lstlisting} + \section{splitnets -- split up multi-bit nets} \label{cmd:splitnets} \begin{lstlisting}[numbers=left,frame=single] @@ -1217,13 +1989,18 @@ primitives. The following internal cell types are mapped by this pass: This command splits multi-bit nets into single-bit nets. - -format char1[char2] + -format char1[char2[char3]] the first char is inserted between the net name and the bit index, the second char is appended to the netname. e.g. -format () creates net - names like 'mysignal(42)'. the default is '[]'. + names like 'mysignal(42)'. the 3rd character is the range separation + character when creating multi-bit wires. the default is '[]:'. -ports also split module ports. per default only internal signals are split. + + -driver + don't blindly split nets in individual bits. instead look at the driver + and split nets so that no driver drives only part of a net. \end{lstlisting} \section{stat -- print some statistics} @@ -1238,6 +2015,10 @@ design. print design hierarchy with this module as top. if the design is fully selected and a module has the 'top' attribute set, this module is used default value for this option. + + -width + annotate internal cell types with their word width. + e.g. $add_8 for an 8 bit wide $add cell. \end{lstlisting} \section{submod -- moving part of a module to a new submodule} @@ -1263,6 +2044,52 @@ Only objects from one module might be selected. The value of the -name option is used as the value of the 'submod' attribute above. \end{lstlisting} +\section{synth -- generic synthesis script} +\label{cmd:synth} +\begin{lstlisting}[numbers=left,frame=single] + synth [options] + +This command runs the default synthesis script. This command does not operate +on partly selected designs. + + -top + use the specified module as top module (default='top') + + -run [:] + only run the commands between the labels (see below). an empty + from label is synonymous to 'begin', and empty to label is + synonymous to the end of the command list. + + +The following commands are executed by this synthesis command: + + begin: + hierarchy -check [-top ] + + coarse: + proc + opt + wreduce + alumacc + share + opt + fsm + opt -fast + memory -nomap + opt_clean + + fine: + opt -fast -full + memory_map + opt -full + techmap + opt -fast + + abc: + abc -fast + opt -fast +\end{lstlisting} + \section{synth\_xilinx -- synthesis for Xilinx FPGAs} \label{cmd:synth_xilinx} \begin{lstlisting}[numbers=left,frame=single] @@ -1340,7 +2167,7 @@ command 'proc' is wrapped using the tcl command 'procs' in order to avoid a name collision with the tcl builting command 'proc'. \end{lstlisting} -\section{techmap -- simple technology mapper} +\section{techmap -- generic technology mapper} \label{cmd:techmap} \begin{lstlisting}[numbers=left,frame=single] techmap [-map filename] [selection] @@ -1355,11 +2182,34 @@ file. transforms the internal RTL cells to the internal gate library. + -map % + like -map above, but with an in-memory design instead of a file. + -share_map filename like -map, but look for the file in the share directory (where the yosys data files are). this is mainly used internally when techmap is called from other commands. + -extern + load the cell implementations as separate modules into the design + instead of inlining them. + + -max_iter + only run the specified number of iterations. + + -recursive + instead of the iterative breadth-first algorithm use a recursive + depth-first algorithm. both methods should yield equivialent results, + but may differ in performance. + + -autoproc + Automatically call "proc" on implementations that contain processes. + + -assert + this option will cause techmap to exit with an error if it can't map + a selected cell. only cell types that end on an underscore are accepted + as final cell types by this mode. + -D , -I this options are passed as-is to the verilog frontend for loading the map file. Note that the verilog frontend is also called with the @@ -1372,6 +2222,13 @@ the module name will be used to match the cell. When a module in the map file has the 'techmap_simplemap' attribute set, techmap will use 'simplemap' (see 'help simplemap') to map cells matching the module. +When a module in the map file has the 'techmap_maccmap' attribute set, techmap +will use 'maccmap' (see 'help maccmap') to map cells matching the module. + +When a module in the map file has the 'techmap_wrap' attribute set, techmap +will create a wrapper for the cell and then run the command string that the +attribute is set to on the wrapper module. + All wires in the modules from the map file matching the pattern _TECHMAP_* or *._TECHMAP_* are special wires that are used to pass instructions from the mapping module to the techmap command. At the moment the following special @@ -1396,6 +2253,20 @@ wires are supported: wire to start out as non-constant and evaluate to a constant value during processing of other _TECHMAP_DO_* commands. + A _TECHMAP_DO_* command may start with the special token 'CONSTMAP; '. + in this case techmap will create a copy for each distinct configuration + of constant inputs and shorted inputs at this point and import the + constant and connected bits into the map module. All further commands + are executed in this copy. This is a very convenient way of creating + optimizied specializations of techmap modules without using the special + parameters described below. + + A _TECHMAP_DO_* command may start with the special token 'RECURSION; '. + then techmap will recursively replace the cells in the module with their + implementation. This is not affected by the -max_iter option. + + It is possible to combine both prefixes to 'RECURSION; CONSTMAP; '. + In addition to this special wires, techmap also supports special parameters in modules in the map file: @@ -1403,21 +2274,70 @@ modules in the map file: When a parameter with this name exists, it will be set to the type name of the cell that matches the module. + _TECHMAP_CONSTMSK__ + _TECHMAP_CONSTVAL__ + When this pair of parameters is available in a module for a port, then + former has a 1-bit for each constant input bit and the latter has the + value for this bit. The unused bits of the latter are set to undef (x). + + _TECHMAP_BITS_CONNMAP_ + _TECHMAP_CONNMAP__ + For an N-bit port, the _TECHMAP_CONNMAP__ parameter, if it + exists, will be set to an N*_TECHMAP_BITS_CONNMAP_ bit vector containing + N words (of _TECHMAP_BITS_CONNMAP_ bits each) that assign each single + bit driver a unique id. The values 0-3 are reserved for 0, 1, x, and z. + This can be used to detect shorted inputs. + When a module in the map file has a parameter where the according cell in the design has a port, the module from the map file is only used if the port in the design is connected to a constant value. The parameter is then set to the constant value. +A cell with the name _TECHMAP_REPLACE_ in the map file will inherit the name +of the cell that is beeing replaced. + See 'help extract' for a pass that does the opposite thing. See 'help flatten' for a pass that does flatten the design (which is esentially techmap but using the design itself as map library). \end{lstlisting} -\section{write\_autotest -- generate simple test benches} -\label{cmd:write_autotest} +\section{tee -- redirect command output to file} +\label{cmd:tee} \begin{lstlisting}[numbers=left,frame=single] - write_autotest [filename] + tee [-q] [-o logfile|-a logfile] cmd + +Execute the specified command, optionally writing the commands output to the +specified logfile(s). + + -q + Do not print output to the normal destination (console and/or log file) + + -o logfile + Write output to this file, truncate if exists. + + -a logfile + Write output to this file, append if exists. +\end{lstlisting} + +\section{test\_abcloop -- automatically test handling of loops in abc command} +\label{cmd:test_abcloop} +\begin{lstlisting}[numbers=left,frame=single] + test_abcloop [options] + +Test handling of logic loops in ABC. + + -n {integer} + create this number of circuits and test them (default = 100). + + -s {positive_integer} + use this value as rng seed value (default = unix time). +\end{lstlisting} + +\section{test\_autotb -- generate simple test benches} +\label{cmd:test_autotb} +\begin{lstlisting}[numbers=left,frame=single] + test_autotb [options] [filename] Automatically create primitive verilog test benches for all modules in the design. The generated testbenches toggle the input pins of the module in @@ -1433,6 +2353,148 @@ be forced to be interpreted as clock signal by setting the attribute The attribute 'gentb_constant' can be used to force a signal to a constant value after initialization. This can e.g. be used to force a reset signal low in order to explore more inner states in a state machine. + + -n + number of iterations the test bench shuld run (default = 1000) +\end{lstlisting} + +\section{test\_cell -- automatically test the implementation of a cell type} +\label{cmd:test_cell} +\begin{lstlisting}[numbers=left,frame=single] + test_cell [options] {cell-types} + +Tests the internal implementation of the given cell type (for example '$add') +by comparing SAT solver, EVAL and TECHMAP implementations of the cell types.. + +Run with 'all' instead of a cell type to run the test on all supported +cell types. + + -n {integer} + create this number of cell instances and test them (default = 100). + + -s {positive_integer} + use this value as rng seed value (default = unix time). + + -f {ilang_file} + don't generate circuits. instead load the specified ilang file. + + -map {filename} + pass this option to techmap. + + -simlib + use "techmap -map +/simlib.v -max_iter 2 -autoproc" + + -script {script_file} + instead of calling "techmap", call "script {script_file}". + + -const + set some input bits to random constant values + + -nosat + do not check SAT model or run SAT equivalence checking + + -v + print additional debug information to the console + + -vlog {filename} + create a verilog test bench to test simlib and write_verilog +\end{lstlisting} + +\section{trace -- redirect command output to file} +\label{cmd:trace} +\begin{lstlisting}[numbers=left,frame=single] + trace cmd + +Execute the specified command, logging all changes the command performs on +the design in real time. +\end{lstlisting} + +\section{verific -- load Verilog and VHDL designs using Verific} +\label{cmd:verific} +\begin{lstlisting}[numbers=left,frame=single] + verific {-vlog95|-vlog2k|-sv2005|-sv2009|-sv} .. + +Load the specified Verilog/SystemVerilog files into Verific. + + + verific {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008} .. + +Load the specified VHDL files into Verific. + + + verific -import [-gates] {-all | ..} + +Elaborate the design for the sepcified top modules, import to Yosys and +reset the internal state of Verific. A gate-level netlist is created +when called with -gates. + +Visit http://verific.com/ for more information on Verific. +\end{lstlisting} + +\section{verilog\_defaults -- set default options for read\_verilog} +\label{cmd:verilog_defaults} +\begin{lstlisting}[numbers=left,frame=single] + verilog_defaults -add [options] + +Add the sepcified options to the list of default options to read_verilog. + + + verilog_defaults -clear +Clear the list of verilog default options. + + + verilog_defaults -push verilog_defaults -pop +Push or pop the list of default options to a stack. Note that -push does +not imply -clear. +\end{lstlisting} + +\section{vhdl2verilog -- importing VHDL designs using vhdl2verilog} +\label{cmd:vhdl2verilog} +\begin{lstlisting}[numbers=left,frame=single] + vhdl2verilog [options] .. + +This command reads VHDL source files using the 'vhdl2verilog' tool and the +Yosys Verilog frontend. + + -out + do not import the vhdl2verilog output. instead write it to the + specified file. + + -vhdl2verilog_dir + do use the specified vhdl2verilog installation. this is the directory + that contains the setup_env.sh file. when this option is not present, + it is assumed that vhdl2verilog is in the PATH environment variable. + + -top + The name of the top entity. This option is mandatory. + +The following options are passed as-is to vhdl2verilog: + + -arch + -unroll_generate + -nogenericeval + -nouniquify + -oldparser + -suppress + -quiet + -nobanner + -mapfile + +vhdl2verilog can be obtained from: +http://www.edautils.com/vhdl2verilog.html +\end{lstlisting} + +\section{wreduce -- reduce the word size of operations is possible} +\label{cmd:wreduce} +\begin{lstlisting}[numbers=left,frame=single] + wreduce [options] [selection] + +This command reduces the word size of operations. For example it will replace +the 32 bit adders in the following code with adders of more appropriate widths: + + module test(input [3:0] a, b, c, output [7:0] y); + assign y = a + b + c + 1; + endmodule \end{lstlisting} \section{write\_blif -- write design to BLIF file} @@ -1456,18 +2518,33 @@ The following options can be useful when the generated file is not going to be read by a BLIF parser but a custom tool. It is recommended to not name the output file *.blif when any of this options is used. - -subckt + -icells do not translate Yosys's internal gates to generic BLIF logic - functions. Instead create .subckt lines for all cells. + functions. Instead create .subckt or .gate lines for all cells. + + -gates + print .gate instead of .subckt lines for all cells that are not + instantiations of other modules from this design. -conn do not generate buffers for connected wires. instead use the non-standard .conn statement. + -param + use the non-standard .param statement to write module parameters + -impltf do not write definitions for the $true and $false wires. \end{lstlisting} +\section{write\_btor -- write design to BTOR file} +\label{cmd:write_btor} +\begin{lstlisting}[numbers=left,frame=single] + write_btor [filename] + +Write the current design to an BTOR file. +\end{lstlisting} + \section{write\_edif -- write design to EDIF netlist file} \label{cmd:write_edif} \begin{lstlisting}[numbers=left,frame=single] @@ -1484,6 +2561,24 @@ necessary to make small modifications to this command when a different tool is targeted. \end{lstlisting} +\section{write\_file -- write a text to a file} +\label{cmd:write_file} +\begin{lstlisting}[numbers=left,frame=single] + write_file [options] output_file [input_file] + +Write the text fron the input file to the output file. + + -a + Append to output file (instead of overwriting) + + +Inside a script the input file can also can a here-document: + + write_file hello.txt < autoloop.old make -C PRESENTATION_Intro diff --git a/manual/presentation.tex b/manual/presentation.tex index 9a876de0c..ee96253a0 100644 --- a/manual/presentation.tex +++ b/manual/presentation.tex @@ -133,7 +133,7 @@ I like writing open source software. For example: \item OpenSCAD (now maintained by Marius Kintel) \item SPL (a not very popular scripting language) \item EmbedVM (a very simple compiler+vm for 8 bit micros) -\item Lib(X)SVF (a library to play SVF/XSVF files over JTAG, used at LHC) +\item Lib(X)SVF (a library to play SVF/XSVF files over JTAG) \item ROCK Linux (discontinued since 2010) \end{itemize} \end{frame} From acf010d30d650aef500952d5de4ea5ec939d78a0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 8 Nov 2014 11:38:44 +0100 Subject: [PATCH 111/492] Added "ENABLE_PLUGINS := 0" to verific amd64 build instructions --- frontends/verific/build_amd64.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/frontends/verific/build_amd64.txt b/frontends/verific/build_amd64.txt index 94615d38d..9bb6e3203 100644 --- a/frontends/verific/build_amd64.txt +++ b/frontends/verific/build_amd64.txt @@ -10,6 +10,7 @@ CONFIG := clang ENABLE_TCL := 0 ENABLE_QT4 := 0 ENABLE_ABC := 0 +ENABLE_PLUGINS := 0 ENABLE_VERIFIC := 1 CXXFLAGS += -m32 LDFLAGS += -m32 From d5aa0ee158b413b24de897a01fc98b02f609f125 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 8 Nov 2014 12:15:01 +0100 Subject: [PATCH 112/492] Yosys 0.4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f6f42b3f7..6909d9031 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ else LDLIBS += -lrt endif -YOSYS_VER := 0.3.0+$(shell test -d .git && { git log --author=clifford@clifford.at --oneline ca125bf41.. | wc -l; }) +YOSYS_VER := 0.4 GIT_REV := $(shell git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN) OBJS = kernel/version_$(GIT_REV).o From 73f5ffcce84299193930e7f580f2cc9367633ab5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 8 Nov 2014 12:20:58 +0100 Subject: [PATCH 113/492] Now we are in Yoys 0.4+ development --- CHANGELOG | 8 +++++++- Makefile | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8679d6c87..5c0626403 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,8 +1,14 @@ -List of changes and major improvements between releases +List of major changes and improvements between releases ======================================================= +Yosys 0.4 .. Yosys 0.4+ +----------------------- + + ... TBD ... + + Yosys 0.3.0 .. Yosys 0.4 ------------------------ diff --git a/Makefile b/Makefile index 6909d9031..10e5bd868 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ else LDLIBS += -lrt endif -YOSYS_VER := 0.4 +YOSYS_VER := 0.4+$(shell test -d .git && { git log --author=clifford@clifford.at --oneline d5aa0ee158b41.. | wc -l; }) GIT_REV := $(shell git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN) OBJS = kernel/version_$(GIT_REV).o From 003336c58dcc9bc96484d6e7a9f3033309a747df Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 8 Nov 2014 12:38:22 +0100 Subject: [PATCH 114/492] Use a cache for log_id() memory management --- kernel/log.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/log.cc b/kernel/log.cc index 99e92e44d..9f5f03b2f 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -44,6 +44,7 @@ bool log_cmd_error_throw = false; int log_verbose_level; std::vector header_count; +std::set log_id_cache; std::list string_buf; int string_buf_size = 0; @@ -214,6 +215,7 @@ void log_push() void log_pop() { header_count.pop_back(); + log_id_cache.clear(); string_buf.clear(); string_buf_size = 0; log_flush(); @@ -223,6 +225,7 @@ void log_reset_stack() { while (header_count.size() > 1) header_count.pop_back(); + log_id_cache.clear(); string_buf.clear(); string_buf_size = 0; log_flush(); @@ -257,8 +260,8 @@ const char *log_signal(const RTLIL::SigSpec &sig, bool autoint) const char *log_id(RTLIL::IdString str) { + log_id_cache.insert(str); const char *p = str.c_str(); - log_assert(RTLIL::IdString::global_refcount_storage_[str.index_] > 1); if (p[0] == '\\' && p[1] != '$' && p[1] != 0) return p+1; return p; From d92fb5b35eff8c616f1b5de355d13b642e830c8f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 8 Nov 2014 12:38:48 +0100 Subject: [PATCH 115/492] Added missing fixup_ports() calls to "rename" command --- passes/cmds/rename.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc index 1006686ef..b2e10e557 100644 --- a/passes/cmds/rename.cc +++ b/passes/cmds/rename.cc @@ -36,6 +36,8 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std:: if (it.first == from_name) { log("Renaming wire %s to %s in module %s.\n", log_id(it.second), log_id(to_name), log_id(module)); module->rename(it.second, to_name); + if (it.second->port_id) + module->fixup_ports(); return; } @@ -124,6 +126,7 @@ struct RenamePass : public Pass { new_wires[it.second->name] = it.second; } module->wires_.swap(new_wires); + module->fixup_ports(); std::map new_cells; for (auto &it : module->cells_) { @@ -154,6 +157,7 @@ struct RenamePass : public Pass { new_wires[it.second->name] = it.second; } module->wires_.swap(new_wires); + module->fixup_ports(); std::map new_cells; for (auto &it : module->cells_) { From 12ffe0c438f0a971da081189524433f9178fa002 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 8 Nov 2014 12:39:01 +0100 Subject: [PATCH 116/492] Some fixes in presentation --- manual/PRESENTATION_Intro.tex | 2 +- manual/presentation.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/manual/PRESENTATION_Intro.tex b/manual/PRESENTATION_Intro.tex index ed600a3e1..5aeebd9f9 100644 --- a/manual/PRESENTATION_Intro.tex +++ b/manual/PRESENTATION_Intro.tex @@ -411,7 +411,7 @@ techmap; opt \end{verbatim} \vfill -\includegraphics[width=\linewidth,trim=0 0cm 0 0cm]{PRESENTATION_Intro/counter_02.pdf} +\includegraphics[width=\linewidth,trim=0 0cm 0 2cm]{PRESENTATION_Intro/counter_02.pdf} \end{frame} \begin{frame}[t, fragile]{\subsecname{} -- Step 4/4} diff --git a/manual/presentation.sh b/manual/presentation.sh index a3557a477..ca8a6c93c 100755 --- a/manual/presentation.sh +++ b/manual/presentation.sh @@ -27,7 +27,7 @@ PDFTEX_OPT="-shell-escape -halt-on-error" set -ex if ! $fast_mode; then - md5sum *.aux *.snm *.nav *.toc > autoloop.old + ! md5sum *.aux *.snm *.nav *.toc > autoloop.old make -C PRESENTATION_Intro make -C PRESENTATION_ExSyn make -C PRESENTATION_ExAdv From cb9e10b4624e6ba6fff215766790e3ff3b82e9a8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 8 Nov 2014 22:19:22 +0100 Subject: [PATCH 117/492] Added automatic "make clean" to abc "hg pull" make rules --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 10e5bd868..13ecc8142 100644 --- a/Makefile +++ b/Makefile @@ -240,9 +240,9 @@ ifneq ($(ABCREV),default) fi $(Q) if test "`cd abc 2> /dev/null && hg identify | cut -f1 -d' '`" != "$(ABCREV)"; then \ test $(ABCPULL) -ne 0 || { echo 'REEBE: NOP abg hc gb qngr naq NOPCHYY frg gb 0 va Znxrsvyr!' | tr 'A-Za-z' 'N-ZA-Mn-za-m'; exit 1; }; \ - echo "Pulling ABC from bitbucket.org:"; \ + echo "Pulling ABC from bitbucket.org:"; set -x; \ test -d abc || hg clone https://bitbucket.org/alanmi/abc abc; \ - cd abc && hg pull && hg update -r $(ABCREV); \ + cd abc && $(MAKE) clean && hg pull && hg update -r $(ABCREV); \ fi endif $(Q) rm -f abc/abc-[0-9a-f]* From fe829bdbdc436f425e082ab1cc8c3d276f168945 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 9 Nov 2014 10:44:23 +0100 Subject: [PATCH 118/492] Added log_warning() API --- backends/spice/spice.cc | 2 +- frontends/ast/genrtlil.cc | 12 ++++++------ frontends/ast/simplify.cc | 8 ++++---- frontends/verific/verific.cc | 2 +- frontends/verilog/verilog_lexer.l | 12 ++++++------ kernel/cost.h | 2 +- kernel/log.cc | 25 +++++++++++++++++++++++-- kernel/log.h | 4 +++- kernel/rtlil.cc | 6 +++--- passes/cmds/select.cc | 2 +- passes/fsm/fsm_detect.cc | 2 +- passes/hierarchy/submod.cc | 4 ++-- passes/proc/proc_dff.cc | 4 ++-- passes/sat/eval.cc | 2 +- passes/sat/sat.cc | 4 ++-- 15 files changed, 57 insertions(+), 34 deletions(-) diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc index 2aff94198..390822ed3 100644 --- a/backends/spice/spice.cc +++ b/backends/spice/spice.cc @@ -58,7 +58,7 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De if (design->modules_.count(cell->type) == 0) { - log("Warning: no (blackbox) module for cell type `%s' (%s.%s) found! Guessing order of ports.\n", + log_warning("no (blackbox) module for cell type `%s' (%s.%s) found! Guessing order of ports.\n", RTLIL::id2cstr(cell->type), RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name)); for (auto &conn : cell->connections()) { RTLIL::SigSpec sig = sigmap(conn.second); diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 68c45179d..4a102370b 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -869,7 +869,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_REALVALUE: { RTLIL::SigSpec sig = realAsConst(width_hint); - log("Warning: converting real value %e to binary %s at %s:%d.\n", + log_warning("converting real value %e to binary %s at %s:%d.\n", realvalue, log_signal(sig), filename.c_str(), linenum); return sig; } @@ -890,7 +890,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); wire->name = str; if (flag_autowire) - log("Warning: Identifier `%s' is implicitly declared at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_warning("Identifier `%s' is implicitly declared at %s:%d.\n", str.c_str(), filename.c_str(), linenum); else log_error("Identifier `%s' is implicitly declared at %s:%d and `default_nettype is set to none.\n", str.c_str(), filename.c_str(), linenum); } @@ -955,10 +955,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk.offset = (id2ast->range_left - id2ast->range_right + 1) - (chunk.offset + chunk.width); if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) { if (chunk.width == 1) - log("Warning: Range select out of bounds on signal `%s' at %s:%d: Setting result bit to undef.\n", + log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting result bit to undef.\n", str.c_str(), filename.c_str(), linenum); else - log("Warning: Range select out of bounds on signal `%s' at %s:%d: Setting all %d result bits to undef.\n", + log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting all %d result bits to undef.\n", str.c_str(), filename.c_str(), linenum, chunk.width); chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width); } else { @@ -972,10 +972,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk.offset += add_undef_bits_lsb; } if (add_undef_bits_lsb) - log("Warning: Range select out of bounds on signal `%s' at %s:%d: Setting %d LSB bits to undef.\n", + log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d LSB bits to undef.\n", str.c_str(), filename.c_str(), linenum, add_undef_bits_lsb); if (add_undef_bits_msb) - log("Warning: Range select out of bounds on signal `%s' at %s:%d: Setting %d MSB bits to undef.\n", + log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d MSB bits to undef.\n", str.c_str(), filename.c_str(), linenum, add_undef_bits_msb); } } diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index d8fdb4c5e..a78fafbd1 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -102,7 +102,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, verbose_activate: if (mem2reg_set.count(mem) == 0) { - log("Warning: Replacing memory %s with list of registers.", mem->str.c_str()); + log_warning("Replacing memory %s with list of registers.", mem->str.c_str()); bool first_element = true; for (auto &place : mem2reg_places[it.first]) { log("%s%s", first_element ? " See " : ", ", place.c_str()); @@ -648,7 +648,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width = children[1]->range_left - children[1]->range_right + 1; if (children[0]->type == AST_REALVALUE) { RTLIL::Const constvalue = children[0]->realAsConst(width); - log("Warning: converting real value %e to binary %s at %s:%d.\n", + log_warning("converting real value %e to binary %s at %s:%d.\n", children[0]->realvalue, log_signal(constvalue), filename.c_str(), linenum); delete children[0]; children[0] = mkconst_bits(constvalue.bits, sign_hint); @@ -690,7 +690,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } } if (current_scope.count(str) == 0) { - // log("Warning: Creating auto-wire `%s' in module `%s'.\n", str.c_str(), current_ast_mod->str.c_str()); + // log_warning("Creating auto-wire `%s' in module `%s'.\n", str.c_str(), current_ast_mod->str.c_str()); AstNode *auto_wire = new AstNode(AST_AUTOWIRE); auto_wire->str = str; current_ast_mod->children.push_back(auto_wire); @@ -1260,7 +1260,7 @@ skip_dynamic_range_lvalue_expansion:; std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN"; if (type == AST_ASSIGN_EQ) - log("Warning: Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n", + log_warning("Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n", filename.c_str(), linenum); int mem_width, mem_size, addr_bits; diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 44dfba0a8..79abcf245 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -730,7 +730,7 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::setIsOperator()) - log("Warning: Unsupported Verific operator: %s (fallback to gate level implementation provided by verific)\n", inst->View()->Owner()->Name()); + log_warning("Unsupported Verific operator: %s (fallback to gate level implementation provided by verific)\n", inst->View()->Owner()->Name()); } else { if (import_netlist_instance_gates(module, net_map, inst)) continue; diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index ae16ebf78..5e739842b 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -254,8 +254,8 @@ supply1 { return TOK_SUPPLY1; } } "/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" { - log("Warning: Found one of those horrible `(synopsys|synthesis) translate_off' comments.\n"); - log("It is strongly suggested to use `ifdef constructs instead!\n"); + log_warning("Found one of those horrible `(synopsys|synthesis) translate_off' comments.\n" + "It is strongly suggested to use `ifdef constructs instead!\n"); BEGIN(SYNOPSYS_TRANSLATE_OFF); } . /* ignore synopsys translate_off body */ @@ -266,13 +266,13 @@ supply1 { return TOK_SUPPLY1; } BEGIN(SYNOPSYS_FLAGS); } full_case { - log("Warning: Found one of those horrible `(synopsys|synthesis) full_case' comments.\n"); - log("It is strongly suggested to use verilog x-values and default branches instead!\n"); + log_warning("Found one of those horrible `(synopsys|synthesis) full_case' comments.\n" + "It is strongly suggested to use verilog x-values and default branches instead!\n"); return TOK_SYNOPSYS_FULL_CASE; } parallel_case { - log("Warning: Found one of those horrible `(synopsys|synthesis) parallel_case' comments.\n"); - log("It is strongly suggested to use verilog `parallel_case' attributes instead!\n"); + log_warning("Found one of those horrible `(synopsys|synthesis) parallel_case' comments.\n" + "It is strongly suggested to use verilog `parallel_case' attributes instead!\n"); return TOK_SYNOPSYS_PARALLEL_CASE; } . /* ignore everything else */ diff --git a/kernel/cost.h b/kernel/cost.h index 5e99df993..61a693b9c 100644 --- a/kernel/cost.h +++ b/kernel/cost.h @@ -70,7 +70,7 @@ int get_cell_cost(RTLIL::IdString type, const std::map> get_coverage_data() for (auto &it : extra_coverage_data) { if (coverage_data.count(it.first)) - log("WARNING: found duplicate coverage id \"%s\".\n", it.first.c_str()); + log_warning("found duplicate coverage id \"%s\".\n", it.first.c_str()); coverage_data[it.first].first = it.second.first; coverage_data[it.first].second += it.second.second; } for (CoverData *p = __start_yosys_cover_list; p != __stop_yosys_cover_list; p++) { if (coverage_data.count(p->id)) - log("WARNING: found duplicate coverage id \"%s\".\n", p->id); + log_warning("found duplicate coverage id \"%s\".\n", p->id); coverage_data[p->id].first = stringf("%s:%d:%s", p->file, p->line, p->func); coverage_data[p->id].second += p->counter; } diff --git a/kernel/log.h b/kernel/log.h index 93e8144a0..b003aba22 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -51,10 +51,12 @@ extern int log_verbose_level; void logv(const char *format, va_list ap); void logv_header(const char *format, va_list ap); +void logv_warning(const char *format, va_list ap); +_NORETURN_ void logv_error(const char *format, va_list ap) __attribute__((noreturn)); -void logv_error(const char *format, va_list ap) __attribute__((noreturn)); void log(const char *format, ...) __attribute__((format(printf, 1, 2))); void log_header(const char *format, ...) __attribute__((format(printf, 1, 2))); +void log_warning(const char *format, ...) __attribute__((format(printf, 1, 2))); _NORETURN_ void log_error(const char *format, ...) __attribute__((format(printf, 1, 2))) __attribute__((noreturn)); _NORETURN_ void log_cmd_error(const char *format, ...) __attribute__((format(printf, 1, 2))) __attribute__((noreturn)); diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 8cfc0c5f9..803d783af 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -440,7 +440,7 @@ std::vector RTLIL::Design::selected_whole_modules_warn() const if (selected_whole_module(it.first)) result.push_back(it.second); else if (selected_module(it.first)) - log("Warning: Ignoring partially selected module %s.\n", log_id(it.first)); + log_warning("Ignoring partially selected module %s.\n", log_id(it.first)); return result; } @@ -1062,14 +1062,14 @@ bool RTLIL::Module::has_processes() const bool RTLIL::Module::has_memories_warn() const { if (!memories.empty()) - log("Warning: Ignoring module %s because it contains memories (run 'memory' command first).\n", log_id(this)); + log_warning("Ignoring module %s because it contains memories (run 'memory' command first).\n", log_id(this)); return !memories.empty(); } bool RTLIL::Module::has_processes_warn() const { if (!processes.empty()) - log("Warning: Ignoring module %s because it contains processes (run 'proc' command first).\n", log_id(this)); + log_warning("Ignoring module %s because it contains processes (run 'proc' command first).\n", log_id(this)); return !processes.empty(); } diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 8e42fe15f..7f841673f 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -532,7 +532,7 @@ static void select_op_expand(RTLIL::Design *design, std::string arg, char mode) } if (rem_objects == 0) - log("Warning: reached configured limit at `%s'.\n", arg.c_str()); + log_warning("reached configured limit at `%s'.\n", arg.c_str()); } static void select_filter_active_mod(RTLIL::Design *design, RTLIL::Selection &sel) diff --git a/passes/fsm/fsm_detect.cc b/passes/fsm/fsm_detect.cc index 84932e963..c89553c6b 100644 --- a/passes/fsm/fsm_detect.cc +++ b/passes/fsm/fsm_detect.cc @@ -43,7 +43,7 @@ static bool check_state_mux_tree(RTLIL::SigSpec old_sig, RTLIL::SigSpec sig, Sig return true; if (recursion_monitor.check_any(sig)) { - log("Warning: logic loop in mux tree at signal %s in module %s.\n", + log_warning("logic loop in mux tree at signal %s in module %s.\n", log_signal(sig), RTLIL::id2cstr(module->name)); return false; } diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 68a441f40..8d4012c53 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -85,7 +85,7 @@ struct SubmodWorker for (auto &conn : cell->connections()) flag_signal(conn.second, true, ct.cell_output(cell->type, conn.first), ct.cell_input(cell->type, conn.first), false, false); } else { - log("WARNING: Port directions for cell %s (%s) are unknown. Assuming inout for all ports.\n", cell->name.c_str(), cell->type.c_str()); + log_warning("Port directions for cell %s (%s) are unknown. Assuming inout for all ports.\n", cell->name.c_str(), cell->type.c_str()); for (auto &conn : cell->connections()) flag_signal(conn.second, true, true, true, false, false); } @@ -102,7 +102,7 @@ struct SubmodWorker for (auto &conn : cell->connections()) flag_signal(conn.second, false, false, false, true, true); if (flag_found_something) - log("WARNING: Port directions for cell %s (%s) are unknown. Assuming inout for all ports.\n", cell->name.c_str(), cell->type.c_str()); + log_warning("Port directions for cell %s (%s) are unknown. Assuming inout for all ports.\n", cell->name.c_str(), cell->type.c_str()); } } diff --git a/passes/proc/proc_dff.cc b/passes/proc/proc_dff.cc index b632cdabb..76842da6b 100644 --- a/passes/proc/proc_dff.cc +++ b/passes/proc/proc_dff.cc @@ -333,12 +333,12 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce) if (many_async_rules.size() > 0) { - log("WARNING: Complex async reset for dff `%s'.\n", log_signal(sig)); + log_warning("Complex async reset for dff `%s'.\n", log_signal(sig)); gen_dffsr_complex(mod, insig, sig, sync_edge->signal, sync_edge->type == RTLIL::SyncType::STp, many_async_rules, proc); } else if (!rstval.is_fully_const() && !ce.eval(rstval)) { - log("WARNING: Async reset value `%s' is not constant!\n", log_signal(rstval)); + log_warning("Async reset value `%s' is not constant!\n", log_signal(rstval)); gen_dffsr(mod, insig, rstval, sig, sync_edge->type == RTLIL::SyncType::STp, sync_level && sync_level->type == RTLIL::SyncType::ST1, diff --git a/passes/sat/eval.cc b/passes/sat/eval.cc index 7a5a02a9b..62534ec0b 100644 --- a/passes/sat/eval.cc +++ b/passes/sat/eval.cc @@ -277,7 +277,7 @@ struct VlogHammerReporter while (!ce.eval(sig, undef)) { // log_error("Evaluation of y in module %s failed: sig=%s, undef=%s\n", RTLIL::id2cstr(module->name), log_signal(sig), log_signal(undef)); - log("Warning: Setting signal %s in module %s to undef.\n", log_signal(undef), RTLIL::id2cstr(module->name)); + log_warning("Setting signal %s in module %s to undef.\n", log_signal(undef), RTLIL::id2cstr(module->name)); ce.set(undef, RTLIL::Const(RTLIL::State::Sx, undef.size())); } diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index d5d1d9160..b73417e87 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -116,7 +116,7 @@ struct SatHelper } if (removed_bits.size()) - log("Warning: ignoring initial value on non-register: %s\n", log_signal(removed_bits)); + log_warning("ignoring initial value on non-register: %s\n", log_signal(removed_bits)); if (lhs.size()) { log("Import set-constraint from init attribute: %s = %s\n", log_signal(lhs), log_signal(rhs)); @@ -327,7 +327,7 @@ struct SatHelper show_drivers.insert(sigmap(p.second), c.second); import_cell_counter++; } else if (ignore_unknown_cells) - log("Warning: Failed to import cell %s (type %s) to SAT database.\n", RTLIL::id2cstr(c.first), RTLIL::id2cstr(c.second->type)); + log_warning("Failed to import cell %s (type %s) to SAT database.\n", RTLIL::id2cstr(c.first), RTLIL::id2cstr(c.second->type)); else log_error("Failed to import cell %s (type %s) to SAT database.\n", RTLIL::id2cstr(c.first), RTLIL::id2cstr(c.second->type)); } From a112b1093444429a1a55a90b73c58c8b7ffee1bc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 9 Nov 2014 10:55:04 +0100 Subject: [PATCH 119/492] Introducing YS_OVERRIDE, YS_FINAL, YS_ATTRIBUTE, YS_NORETURN --- kernel/log.h | 16 ++++++++-------- kernel/modtools.h | 2 +- kernel/register.h | 4 ++-- kernel/yosys.h | 22 +++++++++++++--------- passes/cmds/trace.cc | 12 ++++++------ 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/kernel/log.h b/kernel/log.h index b003aba22..b69e2ee2d 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -52,13 +52,13 @@ extern int log_verbose_level; void logv(const char *format, va_list ap); void logv_header(const char *format, va_list ap); void logv_warning(const char *format, va_list ap); -_NORETURN_ void logv_error(const char *format, va_list ap) __attribute__((noreturn)); +YS_NORETURN void logv_error(const char *format, va_list ap) YS_ATTRIBUTE(noreturn); -void log(const char *format, ...) __attribute__((format(printf, 1, 2))); -void log_header(const char *format, ...) __attribute__((format(printf, 1, 2))); -void log_warning(const char *format, ...) __attribute__((format(printf, 1, 2))); -_NORETURN_ void log_error(const char *format, ...) __attribute__((format(printf, 1, 2))) __attribute__((noreturn)); -_NORETURN_ void log_cmd_error(const char *format, ...) __attribute__((format(printf, 1, 2))) __attribute__((noreturn)); +void log(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); +void log_header(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); +void log_warning(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); +YS_NORETURN void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn); +YS_NORETURN void log_cmd_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn); void log_spacer(); void log_push(); @@ -92,14 +92,14 @@ static inline void log_assert_worker(bool cond, const char *expr, const char *fi #ifdef YOSYS_ENABLE_COVER #define cover(_id) do { \ - static CoverData __d __attribute__((section("yosys_cover_list"), aligned(1), used)) = { __FILE__, __FUNCTION__, _id, __LINE__, 0 }; \ + static CoverData __d YS_ATTRIBUTE(section("yosys_cover_list"), aligned(1), used) = { __FILE__, __FUNCTION__, _id, __LINE__, 0 }; \ __d.counter++; \ } while (0) struct CoverData { const char *file, *func, *id; int line, counter; -} __attribute__ ((packed)); +} YS_ATTRIBUTE(packed); // this two symbols are created by the linker for the "yosys_cover_list" ELF section extern "C" struct CoverData __start_yosys_cover_list[]; diff --git a/kernel/modtools.h b/kernel/modtools.h index 1b6968d74..e3020ae3c 100644 --- a/kernel/modtools.h +++ b/kernel/modtools.h @@ -102,7 +102,7 @@ struct ModIndex : public RTLIL::Monitor auto_reload_module = false; } - virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) OVERRIDE + virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) YS_OVERRIDE { if (auto_reload_module) reload_module(); diff --git a/kernel/register.h b/kernel/register.h index a49675ed2..5214dd9a3 100644 --- a/kernel/register.h +++ b/kernel/register.h @@ -73,7 +73,7 @@ struct Frontend : Pass Frontend(std::string name, std::string short_help = "** document me **"); virtual void run_register(); virtual ~Frontend(); - virtual void execute(std::vector args, RTLIL::Design *design) OVERRIDE FINAL; + virtual void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE YS_FINAL; virtual void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) = 0; static std::vector next_args; @@ -89,7 +89,7 @@ struct Backend : Pass Backend(std::string name, std::string short_help = "** document me **"); virtual void run_register(); virtual ~Backend(); - virtual void execute(std::vector args, RTLIL::Design *design) OVERRIDE FINAL; + virtual void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE YS_FINAL; virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) = 0; void extra_args(std::ostream *&f, std::string &filename, std::vector args, size_t argidx); diff --git a/kernel/yosys.h b/kernel/yosys.h index 11f356adc..b64739ad4 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -102,18 +102,22 @@ #define USING_YOSYS_NAMESPACE using namespace Yosys; #if __cplusplus >= 201103L -# define OVERRIDE override -# define FINAL final +# define YS_OVERRIDE override +# define YS_FINAL final #else -# define OVERRIDE -# define FINAL +# define YS_OVERRIDE +# define YS_FINAL #endif -#if !defined(__GNUC__) && !defined(__clang__) -# define __attribute__(...) -# define _NORETURN_ __declspec(noreturn) +#if defined(__GNUC__) || defined(__clang__) +# define YS_ATTRIBUTE(...) __attribute__((__VA_ARGS__)) +# define YS_NORETURN +#elif defined(_MSC_VER) +# define YS_ATTRIBUTE(...) +# define YS_NORETURN __declspec(noreturn) #else -# define _NORETURN_ +# define YS_ATTRIBUTE(...) +# define YS_NORETURN #endif YOSYS_NAMESPACE_BEGIN @@ -125,7 +129,7 @@ namespace RTLIL { struct Cell; } -std::string stringf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +std::string stringf(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 1, 2)); std::string vstringf(const char *fmt, va_list ap); int readsome(std::istream &f, char *s, int n); std::string next_token(std::string &text, const char *sep); diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc index 10c67195f..e05fedb35 100644 --- a/passes/cmds/trace.cc +++ b/passes/cmds/trace.cc @@ -25,34 +25,34 @@ PRIVATE_NAMESPACE_BEGIN struct TraceMonitor : public RTLIL::Monitor { - virtual void notify_module_add(RTLIL::Module *module) OVERRIDE + virtual void notify_module_add(RTLIL::Module *module) YS_OVERRIDE { log("#TRACE# Module add: %s\n", log_id(module)); } - virtual void notify_module_del(RTLIL::Module *module) OVERRIDE + virtual void notify_module_del(RTLIL::Module *module) YS_OVERRIDE { log("#TRACE# Module delete: %s\n", log_id(module)); } - virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) OVERRIDE + virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) YS_OVERRIDE { log("#TRACE# Cell connect: %s.%s.%s = %s (was: %s)\n", log_id(cell->module), log_id(cell), log_id(port), log_signal(sig), log_signal(old_sig)); } - virtual void notify_connect(RTLIL::Module *module, const RTLIL::SigSig &sigsig) OVERRIDE + virtual void notify_connect(RTLIL::Module *module, const RTLIL::SigSig &sigsig) YS_OVERRIDE { log("#TRACE# Connection in module %s: %s = %s\n", log_id(module), log_signal(sigsig.first), log_signal(sigsig.second)); } - virtual void notify_connect(RTLIL::Module *module, const std::vector &sigsig_vec) OVERRIDE + virtual void notify_connect(RTLIL::Module *module, const std::vector &sigsig_vec) YS_OVERRIDE { log("#TRACE# New connections in module %s:\n", log_id(module)); for (auto &sigsig : sigsig_vec) log("## %s = %s\n", log_signal(sigsig.first), log_signal(sigsig.second)); } - virtual void notify_blackout(RTLIL::Module *module) OVERRIDE + virtual void notify_blackout(RTLIL::Module *module) YS_OVERRIDE { log("#TRACE# Blackout in module %s:\n", log_id(module)); } From 1e0f6b5ddbfc3a7bc30f2537decf45654e7f1524 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 9 Nov 2014 11:02:20 +0100 Subject: [PATCH 120/492] Added "yosys -qq" to also quiet warning messages --- kernel/driver.cc | 5 ++++- kernel/log.cc | 5 +++-- kernel/log.h | 1 + tests/realmath/run-test.sh | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index 8164fef28..7f466839c 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -141,6 +141,8 @@ int main(int argc, char **argv) } break; case 'q': + if (log_errfile == stderr) + log_quiet_warnings = true; log_errfile = stderr; break; case 'v': @@ -170,7 +172,8 @@ int main(int argc, char **argv) fprintf(stderr, " suppress printing of footer (log hash, version, timing statistics)\n"); fprintf(stderr, "\n"); fprintf(stderr, " -q\n"); - fprintf(stderr, " quiet operation. only write error messages to console\n"); + fprintf(stderr, " quiet operation. only write warnings and error messages to console\n"); + fprintf(stderr, " use this option twice to also quiet warning messages\n"); fprintf(stderr, "\n"); fprintf(stderr, " -v \n"); fprintf(stderr, " print log headers up to level to the console. (implies -q)\n"); diff --git a/kernel/log.cc b/kernel/log.cc index 9f9c4db9f..0773429a6 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -41,6 +41,7 @@ SHA1 *log_hasher = NULL; bool log_time = false; bool log_cmd_error_throw = false; +bool log_quiet_warnings = false; int log_verbose_level; std::vector header_count; @@ -154,14 +155,14 @@ void logv_header(const char *format, va_list ap) void logv_warning(const char *format, va_list ap) { - if (log_errfile != NULL) + if (log_errfile != NULL && !log_quiet_warnings) log_files.push_back(log_errfile); log("Warning: "); logv(format, ap); log_flush(); - if (log_errfile != NULL) + if (log_errfile != NULL && !log_quiet_warnings) log_files.pop_back(); } diff --git a/kernel/log.h b/kernel/log.h index b69e2ee2d..278e35b41 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -47,6 +47,7 @@ extern SHA1 *log_hasher; extern bool log_time; extern bool log_cmd_error_throw; +extern bool log_quiet_warnings; extern int log_verbose_level; void logv(const char *format, va_list ap); diff --git a/tests/realmath/run-test.sh b/tests/realmath/run-test.sh index b8e222ad6..0997ccb5d 100755 --- a/tests/realmath/run-test.sh +++ b/tests/realmath/run-test.sh @@ -11,7 +11,7 @@ echo "running tests.." for ((i = 0; i < 100; i++)); do echo -n "[$i]" idx=$( printf "%05d" $i ) - ../../../yosys -q uut_${idx}.ys + ../../../yosys -qq uut_${idx}.ys iverilog -o uut_${idx}_tb uut_${idx}_tb.v uut_${idx}.v uut_${idx}_syn.v ./uut_${idx}_tb | tee uut_${idx}.err if test -s uut_${idx}.err; then From cb1b245a8dd99f1dd65771dc5fa9b89437a36cf1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 12 Nov 2014 00:26:47 +0100 Subject: [PATCH 121/492] Split MXE "make dist" into MXE "make mxebin" and non-MXE "make vcxsrc" --- Makefile | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 13ecc8142..4cf790467 100644 --- a/Makefile +++ b/Makefile @@ -316,9 +316,19 @@ qtcreator: { echo .; find backends frontends kernel libs passes -type f \( -name '*.h' -o -name '*.hh' \) -printf '%h\n' | sort -u; } > qtcreator.includes touch qtcreator.config qtcreator.creator +vcxsrc: $(GENFILES) $(EXTRA_TARGETS) + rm -rf yosys-win32-vcxsrc-$(YOSYS_VER){,.zip} + set -e; for f in $(shell ls $(filter %.cc $.cpp,$(GENFILES)) $(addsuffix .cc,$(basename $(OBJS)) $(addsuffix .cpp,$(basename $(OBJS)))) 2> /dev/null); do \ + echo "Analyse: $$f" >&2; cpp -std=c++11 -MM -I. -D_YOSYS_ $$f; done | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' | sort -u > srcfiles.txt + bash misc/create_vcxsrc.sh yosys-win32-vcxsrc $(YOSYS_VER) $(GIT_REV) + echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys (Version Information Unavailable)\"; }" > kernel/version.cc + zip yosys-win32-vcxsrc-$(YOSYS_VER)/genfiles.zip $(GENFILES) kernel/version.cc + zip -r yosys-win32-vcxsrc-$(YOSYS_VER).zip yosys-win32-vcxsrc-$(YOSYS_VER)/ + rm -f srcfiles.txt kernel/version.cc + ifeq ($(CONFIG),mxe) -dist: $(TARGETS) $(EXTRA_TARGETS) - rm -rf yosys-win32-{mxebin,vcxsrc}-$(YOSYS_VER){,.zip} +mxebin: $(TARGETS) $(EXTRA_TARGETS) + rm -rf yosys-win32-mxebin-$(YOSYS_VER){,.zip} mkdir -p yosys-win32-mxebin-$(YOSYS_VER) cp -r yosys.exe share/ yosys-win32-mxebin-$(YOSYS_VER)/ ifeq ($(ENABLE_ABC),1) @@ -326,14 +336,7 @@ ifeq ($(ENABLE_ABC),1) endif echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-mxebin-$(YOSYS_VER)/readme.txt echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-mxebin-$(YOSYS_VER)/readme.txt - sed -e 's,^[^ ]*:,,; s, ,\n,g; s, *\\,,; s,/[^/]*/\.\./,/,g; s,'"$$PWD/"',,' \ - $(addsuffix .d,$(basename $(OBJS))) | sort -u | grep '^[^/]' | grep -v kernel/version_ > srcfiles.txt - bash misc/create_vcxsrc.sh yosys-win32-vcxsrc $(YOSYS_VER) $(GIT_REV) - echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys (Version Information Unavailable)\"; }" > kernel/version.cc - zip yosys-win32-vcxsrc-$(YOSYS_VER)/genfiles.zip $(GENFILES) kernel/version.cc zip -r yosys-win32-mxebin-$(YOSYS_VER).zip yosys-win32-mxebin-$(YOSYS_VER)/ - zip -r yosys-win32-vcxsrc-$(YOSYS_VER).zip yosys-win32-vcxsrc-$(YOSYS_VER)/ - rm -f srcfiles.txt kernel/version.cc endif config-clean: clean From a8cdcb3dd2f6c0c514008ff83ccad2a4e51ec641 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 12 Nov 2014 00:45:21 +0100 Subject: [PATCH 122/492] Some fixed in "make vcxsrc" srcfiles.txt creation --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4cf790467..057ef43b7 100644 --- a/Makefile +++ b/Makefile @@ -318,8 +318,8 @@ qtcreator: vcxsrc: $(GENFILES) $(EXTRA_TARGETS) rm -rf yosys-win32-vcxsrc-$(YOSYS_VER){,.zip} - set -e; for f in $(shell ls $(filter %.cc $.cpp,$(GENFILES)) $(addsuffix .cc,$(basename $(OBJS)) $(addsuffix .cpp,$(basename $(OBJS)))) 2> /dev/null); do \ - echo "Analyse: $$f" >&2; cpp -std=c++11 -MM -I. -D_YOSYS_ $$f; done | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' | sort -u > srcfiles.txt + set -e; for f in $(wildcard $(filter %.cc %.cpp,$(GENFILES)) $(addsuffix .cc,$(basename $(OBJS))) $(addsuffix .cpp,$(basename $(OBJS))) 2>/dev/null); do \ + echo "Analyse: $$f" >&2; cpp -std=c++11 -MM -I. -D_YOSYS_ $$f; done | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' | sort -u | grep -v kernel/version_ > srcfiles.txt bash misc/create_vcxsrc.sh yosys-win32-vcxsrc $(YOSYS_VER) $(GIT_REV) echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys (Version Information Unavailable)\"; }" > kernel/version.cc zip yosys-win32-vcxsrc-$(YOSYS_VER)/genfiles.zip $(GENFILES) kernel/version.cc From c832b188a54954830a38bf187567187ffad49c31 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 12 Nov 2014 01:17:11 +0100 Subject: [PATCH 123/492] Another 'make vcxsrc' --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 057ef43b7..8e3022ccd 100644 --- a/Makefile +++ b/Makefile @@ -319,7 +319,7 @@ qtcreator: vcxsrc: $(GENFILES) $(EXTRA_TARGETS) rm -rf yosys-win32-vcxsrc-$(YOSYS_VER){,.zip} set -e; for f in $(wildcard $(filter %.cc %.cpp,$(GENFILES)) $(addsuffix .cc,$(basename $(OBJS))) $(addsuffix .cpp,$(basename $(OBJS))) 2>/dev/null); do \ - echo "Analyse: $$f" >&2; cpp -std=c++11 -MM -I. -D_YOSYS_ $$f; done | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' | sort -u | grep -v kernel/version_ > srcfiles.txt + echo "Analyse: $$f" >&2; cpp -std=gnu++0x -MM -I. -D_YOSYS_ $$f; done | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' | sort -u | grep -v kernel/version_ > srcfiles.txt bash misc/create_vcxsrc.sh yosys-win32-vcxsrc $(YOSYS_VER) $(GIT_REV) echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys (Version Information Unavailable)\"; }" > kernel/version.cc zip yosys-win32-vcxsrc-$(YOSYS_VER)/genfiles.zip $(GENFILES) kernel/version.cc From 4e5350b409877ecc804cb3ee9a8ab0cb1a3773d9 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 12 Nov 2014 19:10:35 +0100 Subject: [PATCH 124/492] Fixed parsing of nested verilog concatenation and replicate --- frontends/verilog/verilog_parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 0902e58a2..e40bc188b 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1321,7 +1321,7 @@ basic_expr: '{' concat_list '}' { $$ = $2; } | - '{' expr '{' expr '}' '}' { + '{' expr '{' concat_list '}' '}' { $$ = new AstNode(AST_REPLICATE, $2, $4); } | '~' attr basic_expr %prec UNARY_OPS { From 87333f3ae236555ac1efb38b5e99b5f067900ddd Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 14 Nov 2014 19:59:50 +0100 Subject: [PATCH 125/492] Added warning for use of 'z' constants in HDL --- frontends/verilog/const2ast.cc | 10 +++++++++- frontends/verilog/verilog_frontend.h | 2 +- frontends/verilog/verilog_parser.y | 8 ++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index a81e3010f..ca995915f 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -132,8 +132,16 @@ static void my_strtobin(std::vector &data, const char *str, int le } // convert the verilog code for a constant to an AST node -AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type) +AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn_z) { + if (warn_z) { + AstNode *ret = const2ast(code, case_type); + if (std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end()) + log_warning("Yosys does not support tri-state logic at the moment. (%s:%d)\n", + current_filename.c_str(), frontend_verilog_yyget_lineno()); + return ret; + } + const char *str = code.c_str(); // Strings diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h index af6495f8f..e277f3e3c 100644 --- a/frontends/verilog/verilog_frontend.h +++ b/frontends/verilog/verilog_frontend.h @@ -43,7 +43,7 @@ namespace VERILOG_FRONTEND extern struct AST::AstNode *current_ast; // this function converts a Verilog constant to an AST_CONSTANT node - AST::AstNode *const2ast(std::string code, char case_type = 0); + AST::AstNode *const2ast(std::string code, char case_type = 0, bool warn_z = false); // state of `default_nettype extern bool default_nettype_wire; diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index e40bc188b..75af46522 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1251,7 +1251,7 @@ basic_expr: if ($4->substr(0, 1) != "'") frontend_verilog_yyerror("Syntax error."); AstNode *bits = $2; - AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back()); + AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), true); if (val == NULL) log_error("Value conversion failed: `%s'\n", $4->c_str()); $$ = new AstNode(AST_TO_BITS, bits, val); @@ -1262,7 +1262,7 @@ basic_expr: frontend_verilog_yyerror("Syntax error."); AstNode *bits = new AstNode(AST_IDENTIFIER); bits->str = *$1; - AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back()); + AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), true); if (val == NULL) log_error("Value conversion failed: `%s'\n", $2->c_str()); $$ = new AstNode(AST_TO_BITS, bits, val); @@ -1270,14 +1270,14 @@ basic_expr: delete $2; } | TOK_CONST TOK_CONST { - $$ = const2ast(*$1 + *$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back()); + $$ = const2ast(*$1 + *$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), true); if ($$ == NULL || (*$2)[0] != '\'') log_error("Value conversion failed: `%s%s'\n", $1->c_str(), $2->c_str()); delete $1; delete $2; } | TOK_CONST { - $$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back()); + $$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), true); if ($$ == NULL) log_error("Value conversion failed: `%s'\n", $1->c_str()); delete $1; From 76cc2bf7b43140698618e9dbb87a219c3bd7d32f Mon Sep 17 00:00:00 2001 From: SlowRiot Date: Thu, 20 Nov 2014 01:58:57 +0000 Subject: [PATCH 126/492] fixing incorrect buffer size allocation, and unsafe integer size type --- libs/sha1/sha1.cpp | 86 ++++++++++++++++++++++++---------------------- libs/sha1/sha1.h | 38 ++++++++++---------- 2 files changed, 64 insertions(+), 60 deletions(-) diff --git a/libs/sha1/sha1.cpp b/libs/sha1/sha1.cpp index 883d42837..3d46da7be 100644 --- a/libs/sha1/sha1.cpp +++ b/libs/sha1/sha1.cpp @@ -1,55 +1,57 @@ /* sha1.cpp - source code of - + ============ SHA-1 in C++ ============ - + 100% Public Domain. - + Original C Code -- Steve Reid Small changes to fit into bglibs -- Bruce Guenter Translation to simpler C++ Code -- Volker Grabsch + Fixing bugs and improving style + -- Eugene Hopkinson */ - + #include "sha1.h" #include #include #include - + /* Help macros */ #define SHA1_ROL(value, bits) (((value) << (bits)) | (((value) & 0xffffffff) >> (32 - (bits)))) #define SHA1_BLK(i) (block[i&15] = SHA1_ROL(block[(i+13)&15] ^ block[(i+8)&15] ^ block[(i+2)&15] ^ block[i&15],1)) - + /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ #define SHA1_R0(v,w,x,y,z,i) z += ((w&(x^y))^y) + block[i] + 0x5a827999 + SHA1_ROL(v,5); w=SHA1_ROL(w,30); #define SHA1_R1(v,w,x,y,z,i) z += ((w&(x^y))^y) + SHA1_BLK(i) + 0x5a827999 + SHA1_ROL(v,5); w=SHA1_ROL(w,30); #define SHA1_R2(v,w,x,y,z,i) z += (w^x^y) + SHA1_BLK(i) + 0x6ed9eba1 + SHA1_ROL(v,5); w=SHA1_ROL(w,30); #define SHA1_R3(v,w,x,y,z,i) z += (((w|x)&y)|(w&x)) + SHA1_BLK(i) + 0x8f1bbcdc + SHA1_ROL(v,5); w=SHA1_ROL(w,30); #define SHA1_R4(v,w,x,y,z,i) z += (w^x^y) + SHA1_BLK(i) + 0xca62c1d6 + SHA1_ROL(v,5); w=SHA1_ROL(w,30); - + SHA1::SHA1() { reset(); } - - + + void SHA1::update(const std::string &s) { std::istringstream is(s); update(is); } - - + + void SHA1::update(std::istream &is) { std::string rest_of_buffer; read(is, rest_of_buffer, BLOCK_BYTES - buffer.size()); buffer += rest_of_buffer; - + while (is) { uint32 block[BLOCK_INTS]; @@ -58,17 +60,17 @@ void SHA1::update(std::istream &is) read(is, buffer, BLOCK_BYTES); } } - - + + /* * Add padding and return the message digest. */ - + std::string SHA1::final() { /* Total number of hashed bits */ uint64 total_bits = (transforms*BLOCK_BYTES + buffer.size()) * 8; - + /* Padding */ buffer += 0x80; unsigned int orig_size = buffer.size(); @@ -76,10 +78,10 @@ std::string SHA1::final() { buffer += (char)0x00; } - + uint32 block[BLOCK_INTS]; buffer_to_block(buffer, block); - + if (orig_size > BLOCK_BYTES - 8) { transform(block); @@ -88,12 +90,12 @@ std::string SHA1::final() block[i] = 0; } } - + /* Append total_bits, split this uint64 into two uint32 */ block[BLOCK_INTS - 1] = total_bits; block[BLOCK_INTS - 2] = (total_bits >> 32); transform(block); - + /* Hex std::string */ std::ostringstream result; for (unsigned int i = 0; i < DIGEST_INTS; i++) @@ -101,14 +103,14 @@ std::string SHA1::final() result << std::hex << std::setfill('0') << std::setw(8); result << (digest[i] & 0xffffffff); } - + /* Reset for next run */ reset(); - + return result.str(); } - - + + std::string SHA1::from_file(const std::string &filename) { std::ifstream stream(filename.c_str(), std::ios::binary); @@ -116,8 +118,8 @@ std::string SHA1::from_file(const std::string &filename) checksum.update(stream); return checksum.final(); } - - + + void SHA1::reset() { /* SHA1 initialization constants */ @@ -126,17 +128,17 @@ void SHA1::reset() digest[2] = 0x98badcfe; digest[3] = 0x10325476; digest[4] = 0xc3d2e1f0; - + /* Reset counters */ transforms = 0; buffer = ""; } - - + + /* * Hash a single 512-bit block. This is the core of the algorithm. */ - + void SHA1::transform(uint32 block[BLOCK_BYTES]) { /* Copy digest[] to working vars */ @@ -145,8 +147,8 @@ void SHA1::transform(uint32 block[BLOCK_BYTES]) uint32 c = digest[2]; uint32 d = digest[3]; uint32 e = digest[4]; - - + + /* 4 rounds of 20 operations each. Loop unrolled. */ SHA1_R0(a,b,c,d,e, 0); SHA1_R0(e,a,b,c,d, 1); @@ -228,20 +230,20 @@ void SHA1::transform(uint32 block[BLOCK_BYTES]) SHA1_R4(d,e,a,b,c,77); SHA1_R4(c,d,e,a,b,78); SHA1_R4(b,c,d,e,a,79); - + /* Add the working vars back into digest[] */ digest[0] += a; digest[1] += b; digest[2] += c; digest[3] += d; digest[4] += e; - + /* Count the number of transformations */ transforms++; } - - -void SHA1::buffer_to_block(const std::string &buffer, uint32 block[BLOCK_BYTES]) + + +void SHA1::buffer_to_block(const std::string &buffer, uint32 block[BLOCK_INTS]) { /* Convert the std::string (byte buffer) to a uint32 array (MSB) */ for (unsigned int i = 0; i < BLOCK_INTS; i++) @@ -252,9 +254,9 @@ void SHA1::buffer_to_block(const std::string &buffer, uint32 block[BLOCK_BYTES]) | (buffer[4*i+0] & 0xff)<<24; } } - - -void SHA1::read(std::istream &is, std::string &s, int max) + + +void SHA1::read(std::istream &is, std::string &s, size_t max) { char* sbuf = new char[max]; @@ -263,8 +265,8 @@ void SHA1::read(std::istream &is, std::string &s, int max) delete[] sbuf; } - - + + std::string sha1(const std::string &string) { SHA1 checksum; diff --git a/libs/sha1/sha1.h b/libs/sha1/sha1.h index 15edee12e..898575d6c 100644 --- a/libs/sha1/sha1.h +++ b/libs/sha1/sha1.h @@ -1,27 +1,29 @@ /* sha1.h - header of - + ============ SHA-1 in C++ ============ - + 100% Public Domain. - + Original C Code -- Steve Reid Small changes to fit into bglibs -- Bruce Guenter Translation to simpler C++ Code -- Volker Grabsch + Fixing bugs and improving style + -- Eugene Hopkinson */ - + #ifndef SHA1_HPP #define SHA1_HPP - - + + #include #include - + class SHA1 { public: @@ -30,28 +32,28 @@ public: void update(std::istream &is); std::string final(); static std::string from_file(const std::string &filename); - + private: typedef unsigned long int uint32; /* just needs to be at least 32bit */ typedef unsigned long long uint64; /* just needs to be at least 64bit */ - + static const unsigned int DIGEST_INTS = 5; /* number of 32bit integers per SHA1 digest */ static const unsigned int BLOCK_INTS = 16; /* number of 32bit integers per SHA1 block */ static const unsigned int BLOCK_BYTES = BLOCK_INTS * 4; - + uint32 digest[DIGEST_INTS]; std::string buffer; uint64 transforms; - + void reset(); void transform(uint32 block[BLOCK_BYTES]); - - static void buffer_to_block(const std::string &buffer, uint32 block[BLOCK_BYTES]); - static void read(std::istream &is, std::string &s, int max); + + static void read(std::istream &is, std::string &s, size_t max); + static void buffer_to_block(const std::string &buffer, uint32 block[BLOCK_INTS]); }; - + std::string sha1(const std::string &string); - - - + + + #endif /* SHA1_HPP */ From 4aae465867cd1221e47eaaa7550f1eb9aa2f5863 Mon Sep 17 00:00:00 2001 From: SlowRiot Date: Thu, 20 Nov 2014 02:03:08 +0000 Subject: [PATCH 127/492] switching from unreliable typedefs to precisely sized uint32_t and uint64_t --- libs/sha1/sha1.cpp | 24 ++++++++++++------------ libs/sha1/sha1.h | 11 ++++------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/libs/sha1/sha1.cpp b/libs/sha1/sha1.cpp index 3d46da7be..51bbd85c8 100644 --- a/libs/sha1/sha1.cpp +++ b/libs/sha1/sha1.cpp @@ -54,7 +54,7 @@ void SHA1::update(std::istream &is) while (is) { - uint32 block[BLOCK_INTS]; + uint32_t block[BLOCK_INTS]; buffer_to_block(buffer, block); transform(block); read(is, buffer, BLOCK_BYTES); @@ -69,7 +69,7 @@ void SHA1::update(std::istream &is) std::string SHA1::final() { /* Total number of hashed bits */ - uint64 total_bits = (transforms*BLOCK_BYTES + buffer.size()) * 8; + uint64_t total_bits = (transforms*BLOCK_BYTES + buffer.size()) * 8; /* Padding */ buffer += 0x80; @@ -79,7 +79,7 @@ std::string SHA1::final() buffer += (char)0x00; } - uint32 block[BLOCK_INTS]; + uint32_t block[BLOCK_INTS]; buffer_to_block(buffer, block); if (orig_size > BLOCK_BYTES - 8) @@ -91,7 +91,7 @@ std::string SHA1::final() } } - /* Append total_bits, split this uint64 into two uint32 */ + /* Append total_bits, split this uint64_t into two uint32_t */ block[BLOCK_INTS - 1] = total_bits; block[BLOCK_INTS - 2] = (total_bits >> 32); transform(block); @@ -139,14 +139,14 @@ void SHA1::reset() * Hash a single 512-bit block. This is the core of the algorithm. */ -void SHA1::transform(uint32 block[BLOCK_BYTES]) +void SHA1::transform(uint32_t block[BLOCK_BYTES]) { /* Copy digest[] to working vars */ - uint32 a = digest[0]; - uint32 b = digest[1]; - uint32 c = digest[2]; - uint32 d = digest[3]; - uint32 e = digest[4]; + uint32_t a = digest[0]; + uint32_t b = digest[1]; + uint32_t c = digest[2]; + uint32_t d = digest[3]; + uint32_t e = digest[4]; /* 4 rounds of 20 operations each. Loop unrolled. */ @@ -243,9 +243,9 @@ void SHA1::transform(uint32 block[BLOCK_BYTES]) } -void SHA1::buffer_to_block(const std::string &buffer, uint32 block[BLOCK_INTS]) +void SHA1::buffer_to_block(const std::string &buffer, uint32_t block[BLOCK_INTS]) { - /* Convert the std::string (byte buffer) to a uint32 array (MSB) */ + /* Convert the std::string (byte buffer) to a uint32_t array (MSB) */ for (unsigned int i = 0; i < BLOCK_INTS; i++) { block[i] = (buffer[4*i+3] & 0xff) diff --git a/libs/sha1/sha1.h b/libs/sha1/sha1.h index 898575d6c..f6a03e735 100644 --- a/libs/sha1/sha1.h +++ b/libs/sha1/sha1.h @@ -34,22 +34,19 @@ public: static std::string from_file(const std::string &filename); private: - typedef unsigned long int uint32; /* just needs to be at least 32bit */ - typedef unsigned long long uint64; /* just needs to be at least 64bit */ - static const unsigned int DIGEST_INTS = 5; /* number of 32bit integers per SHA1 digest */ static const unsigned int BLOCK_INTS = 16; /* number of 32bit integers per SHA1 block */ static const unsigned int BLOCK_BYTES = BLOCK_INTS * 4; - uint32 digest[DIGEST_INTS]; + uint32_t digest[DIGEST_INTS]; std::string buffer; - uint64 transforms; + uint64_t transforms; void reset(); - void transform(uint32 block[BLOCK_BYTES]); + void transform(uint32_t block[BLOCK_BYTES]); static void read(std::istream &is, std::string &s, size_t max); - static void buffer_to_block(const std::string &buffer, uint32 block[BLOCK_INTS]); + static void buffer_to_block(const std::string &buffer, uint32_t block[BLOCK_INTS]); }; std::string sha1(const std::string &string); From 751fb33688b06d8dab01b7f8334055d5cd227c94 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 24 Nov 2014 12:55:30 +0100 Subject: [PATCH 128/492] Some fixes in stubnets example --- manual/CHAPTER_Prog/stubnets.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/manual/CHAPTER_Prog/stubnets.cc b/manual/CHAPTER_Prog/stubnets.cc index 8880af5a6..4849c6a7b 100644 --- a/manual/CHAPTER_Prog/stubnets.cc +++ b/manual/CHAPTER_Prog/stubnets.cc @@ -5,15 +5,16 @@ // binary, for any purpose, commercial or non-commercial, and by any // means. -#include "kernel/rtlil.h" -#include "kernel/register.h" +#include "kernel/yosys.h" #include "kernel/sigtools.h" -#include "kernel/log.h" #include #include #include +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + // this function is called for each module in the design static void find_stub_nets(RTLIL::Design *design, RTLIL::Module *module, bool report_bits) { @@ -126,3 +127,4 @@ struct StubnetsPass : public Pass { } } StubnetsPass; +PRIVATE_NAMESPACE_END From 56c7d1e266cf6b2f9bfcb9f76f2ddf388ddc51ea Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 24 Nov 2014 14:39:24 +0100 Subject: [PATCH 129/492] Fixed two minor bugs in constant parsing --- frontends/verilog/const2ast.cc | 6 +++++- frontends/verilog/verilog_lexer.l | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index ca995915f..735bc5f99 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -182,7 +182,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn if (str == endptr) len_in_bits = -1; - // The "'s?[bodh]" syntax + // The "'s?[bodhBODH]" syntax if (*endptr == '\'') { std::vector data; @@ -194,15 +194,19 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn switch (*(endptr+1)) { case 'b': + case 'B': my_strtobin(data, endptr+2, len_in_bits, 2, case_type); break; case 'o': + case 'O': my_strtobin(data, endptr+2, len_in_bits, 8, case_type); break; case 'd': + case 'D': my_strtobin(data, endptr+2, len_in_bits, 10, case_type); break; case 'h': + case 'H': my_strtobin(data, endptr+2, len_in_bits, 16, case_type); break; default: diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 5e739842b..c3dfa8b92 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -177,12 +177,12 @@ YOSYS_NAMESPACE_END "genvar" { return TOK_GENVAR; } "real" { return TOK_REAL; } -[0-9]+ { +[0-9][0-9_]* { frontend_verilog_yylval.string = new std::string(yytext); return TOK_CONST; } -[0-9]*[ \t]*\'s?[bodh][ \t\r\n]*[0-9a-fA-FzxZX?_]+ { +[0-9]*[ \t]*\'s?[bodhBODH][ \t\r\n]*[0-9a-fA-FzxZX?_]+ { frontend_verilog_yylval.string = new std::string(yytext); return TOK_CONST; } From 76c83283c44267969b96dc53bf02775aa950b5be Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 24 Nov 2014 14:48:07 +0100 Subject: [PATCH 130/492] Fixed minor bug in parsing delays --- frontends/verilog/verilog_lexer.l | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index c3dfa8b92..74a66d964 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -342,7 +342,10 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ { [ \t\r\n] /* ignore whitespaces */ \\[\r\n] /* ignore continuation sequence */ "//"[^\r\n]* /* ignore one-line comments */ -"#"[$a-zA-Z_0-9\.]+ /* ignore simulation timings */ + +"#"\ *[0-9][0-9_]* /* ignore simulation timings */ +"#"\ *[0-9][0-9_]*\.[0-9][0-9_]* /* ignore simulation timings */ +"#"\ *[$a-zA-Z_\.][$a-zA-Z_0-9\.]* /* ignore simulation timings */ . { return *yytext; } From 51cfcd8331bb06b1fea3ec62a48fcbb092e7df70 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 27 Nov 2014 12:47:33 +0100 Subject: [PATCH 131/492] Fixed bug in "hierarchy -top" with array of instances --- passes/hierarchy/hierarchy.cc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 0ea26eb9e..e070afdd5 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -259,9 +259,16 @@ void hierarchy_worker(RTLIL::Design *design, std::set &used, RTL log("Used module: %*s%s\n", indent, "", mod->name.c_str()); used.insert(mod); - for (auto &it : mod->cells_) { - if (design->modules_.count(it.second->type) > 0) - hierarchy_worker(design, used, design->modules_[it.second->type], indent+4); + for (auto cell : mod->cells()) { + std::string celltype = cell->type.str(); + if (celltype.substr(0, 7) == "$array:") { + int pos_idx = celltype.find_first_of(':'); + int pos_num = celltype.find_first_of(':', pos_idx + 1); + int pos_type = celltype.find_first_of(':', pos_num + 1); + celltype = celltype.substr(pos_type + 1); + } + if (design->module(celltype)) + hierarchy_worker(design, used, design->module(celltype), indent+4); } } From abf81d76835d3ebb372ea128ee15cf6fb2c8f03a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 4 Dec 2014 13:37:58 +0100 Subject: [PATCH 132/492] Added some missing .gitignore in manual/ --- manual/CHAPTER_Prog/.gitignore | 3 +++ manual/PRESENTATION_Prog/.gitignore | 1 + 2 files changed, 4 insertions(+) create mode 100644 manual/CHAPTER_Prog/.gitignore diff --git a/manual/CHAPTER_Prog/.gitignore b/manual/CHAPTER_Prog/.gitignore new file mode 100644 index 000000000..fa83c3212 --- /dev/null +++ b/manual/CHAPTER_Prog/.gitignore @@ -0,0 +1,3 @@ +stubnets.so +stubnets.d +*.log diff --git a/manual/PRESENTATION_Prog/.gitignore b/manual/PRESENTATION_Prog/.gitignore index 7fd560762..ccdd6bd5c 100644 --- a/manual/PRESENTATION_Prog/.gitignore +++ b/manual/PRESENTATION_Prog/.gitignore @@ -1 +1,2 @@ my_cmd.so +my_cmd.d From e65033e42137d351b6d948a402e968646432da6b Mon Sep 17 00:00:00 2001 From: Fabien Marteau Date: Fri, 5 Dec 2014 18:17:00 +0100 Subject: [PATCH 133/492] suppressing semi-colon at the end of dot files --- manual/APPNOTE_011_Design_Investigation/cmos_00.dot | 2 +- manual/APPNOTE_011_Design_Investigation/cmos_01.dot | 2 +- manual/APPNOTE_011_Design_Investigation/example_00.dot | 2 +- manual/APPNOTE_011_Design_Investigation/example_01.dot | 2 +- manual/APPNOTE_011_Design_Investigation/example_02.dot | 2 +- manual/APPNOTE_011_Design_Investigation/example_03.dot | 2 +- manual/APPNOTE_011_Design_Investigation/memdemo_00.dot | 2 +- manual/APPNOTE_011_Design_Investigation/memdemo_01.dot | 2 +- manual/APPNOTE_011_Design_Investigation/splice.dot | 2 +- manual/APPNOTE_011_Design_Investigation/submod_00.dot | 2 +- manual/APPNOTE_011_Design_Investigation/submod_01.dot | 2 +- manual/APPNOTE_011_Design_Investigation/submod_02.dot | 2 +- manual/APPNOTE_011_Design_Investigation/submod_03.dot | 2 +- manual/APPNOTE_011_Design_Investigation/sumprod_00.dot | 2 +- manual/APPNOTE_011_Design_Investigation/sumprod_01.dot | 2 +- manual/APPNOTE_011_Design_Investigation/sumprod_02.dot | 2 +- manual/APPNOTE_011_Design_Investigation/sumprod_03.dot | 2 +- manual/APPNOTE_011_Design_Investigation/sumprod_04.dot | 2 +- manual/APPNOTE_011_Design_Investigation/sumprod_05.dot | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/manual/APPNOTE_011_Design_Investigation/cmos_00.dot b/manual/APPNOTE_011_Design_Investigation/cmos_00.dot index 85ca78492..49c630080 100644 --- a/manual/APPNOTE_011_Design_Investigation/cmos_00.dot +++ b/manual/APPNOTE_011_Design_Investigation/cmos_00.dot @@ -31,4 +31,4 @@ n5:e -> c11:p7:w [color="black", label=""]; n6:e -> x0:s0:w [color="black", label=""]; n6:e -> x1:s0:w [color="black", label=""]; n6:e -> x2:s0:w [color="black", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/cmos_01.dot b/manual/APPNOTE_011_Design_Investigation/cmos_01.dot index de9af1704..ea6f4403c 100644 --- a/manual/APPNOTE_011_Design_Investigation/cmos_01.dot +++ b/manual/APPNOTE_011_Design_Investigation/cmos_01.dot @@ -20,4 +20,4 @@ n5:e -> c12:p8:w [color="black", label=""]; c15:p10:e -> n6:w [color="black", label=""]; c14:p10:e -> n7:w [color="black", label=""]; n7:e -> c15:p9:w [color="black", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/example_00.dot b/manual/APPNOTE_011_Design_Investigation/example_00.dot index b38862c4b..1e23ed0ea 100644 --- a/manual/APPNOTE_011_Design_Investigation/example_00.dot +++ b/manual/APPNOTE_011_Design_Investigation/example_00.dot @@ -20,4 +20,4 @@ n7:e -> p1:w [color="black", label=""]; p1:e -> n8:w [color="black", style="setlinewidth(3)", label=""]; n8:e -> p1:w [color="black", style="setlinewidth(3)", label=""]; v0:e -> c14:p9:w [color="black", style="setlinewidth(3)", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/example_01.dot b/manual/APPNOTE_011_Design_Investigation/example_01.dot index e2e3f02d4..e89292b51 100644 --- a/manual/APPNOTE_011_Design_Investigation/example_01.dot +++ b/manual/APPNOTE_011_Design_Investigation/example_01.dot @@ -30,4 +30,4 @@ n8:e -> c21:p19:w [color="black", label=""]; n8:e -> x1:w:w [color="black", label=""]; n9:e -> c18:p15:w [color="black", label=""]; v0:e -> c21:p11:w [color="black", style="setlinewidth(3)", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/example_02.dot b/manual/APPNOTE_011_Design_Investigation/example_02.dot index 4b57f89c1..f950ed2ed 100644 --- a/manual/APPNOTE_011_Design_Investigation/example_02.dot +++ b/manual/APPNOTE_011_Design_Investigation/example_02.dot @@ -17,4 +17,4 @@ n5:e -> c17:p16:w [color="black", label=""]; n6:e -> c15:p12:w [color="black", label=""]; c15:p14:e -> n7:w [color="black", style="setlinewidth(3)", label=""]; n7:e -> c17:p8:w [color="black", style="setlinewidth(3)", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/example_03.dot b/manual/APPNOTE_011_Design_Investigation/example_03.dot index 6c00c29aa..e19d24af7 100644 --- a/manual/APPNOTE_011_Design_Investigation/example_03.dot +++ b/manual/APPNOTE_011_Design_Investigation/example_03.dot @@ -8,4 +8,4 @@ c4 [ shape=record, label="{{ A| B}|$2\n$add|{ Y}}" ]; v0:e -> c4:p1:w [color="black", label=""]; v1:e -> c4:p2:w [color="black", label=""]; c4:p3:e -> v2:w [color="black", style="setlinewidth(3)", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/memdemo_00.dot b/manual/APPNOTE_011_Design_Investigation/memdemo_00.dot index 9e81edbce..0336a9aac 100644 --- a/manual/APPNOTE_011_Design_Investigation/memdemo_00.dot +++ b/manual/APPNOTE_011_Design_Investigation/memdemo_00.dot @@ -135,4 +135,4 @@ v6:e -> c47:p34:w [color="black", label=""]; v7:e -> c48:p33:w [color="black", style="setlinewidth(3)", label=""]; v8:e -> c49:p33:w [color="black", style="setlinewidth(3)", label=""]; v9:e -> c50:p33:w [color="black", style="setlinewidth(3)", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/memdemo_01.dot b/manual/APPNOTE_011_Design_Investigation/memdemo_01.dot index bbd7fcc63..2ad92c78b 100644 --- a/manual/APPNOTE_011_Design_Investigation/memdemo_01.dot +++ b/manual/APPNOTE_011_Design_Investigation/memdemo_01.dot @@ -26,4 +26,4 @@ v0:e -> c13:p11:w [color="black", label=""]; v1:e -> c14:p11:w [color="black", label=""]; v2:e -> c15:p11:w [color="black", label=""]; v3:e -> c19:p16:w [color="black", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/splice.dot b/manual/APPNOTE_011_Design_Investigation/splice.dot index 1bcd55b42..4657feed1 100644 --- a/manual/APPNOTE_011_Design_Investigation/splice.dot +++ b/manual/APPNOTE_011_Design_Investigation/splice.dot @@ -36,4 +36,4 @@ x1:s0:e -> n8:w [color="black", style="setlinewidth(3)", label=""]; x3:s0:e -> n8:w [color="black", style="setlinewidth(3)", label=""]; x3:s1:e -> n8:w [color="black", style="setlinewidth(3)", label=""]; x6:s0:e -> n8:w [color="black", style="setlinewidth(3)", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/submod_00.dot b/manual/APPNOTE_011_Design_Investigation/submod_00.dot index 4567dfb43..2e55268ee 100644 --- a/manual/APPNOTE_011_Design_Investigation/submod_00.dot +++ b/manual/APPNOTE_011_Design_Investigation/submod_00.dot @@ -42,4 +42,4 @@ c21:p8:e -> n8:w [color="black", style="setlinewidth(3)", label=""]; n8:e -> c20:p8:w [color="black", style="setlinewidth(3)", label=""]; c21:p9:e -> n9:w [color="black", style="setlinewidth(3)", label=""]; n9:e -> c20:p9:w [color="black", style="setlinewidth(3)", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/submod_01.dot b/manual/APPNOTE_011_Design_Investigation/submod_01.dot index b1daae23a..f8f8c008a 100644 --- a/manual/APPNOTE_011_Design_Investigation/submod_01.dot +++ b/manual/APPNOTE_011_Design_Investigation/submod_01.dot @@ -84,4 +84,4 @@ v4:e -> c35:p24:w [color="black", style="setlinewidth(3)", label=""]; v5:e -> c36:p24:w [color="black", style="setlinewidth(3)", label=""]; v6:e -> c37:p24:w [color="black", style="setlinewidth(3)", label=""]; v7:e -> c38:p24:w [color="black", style="setlinewidth(3)", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/submod_02.dot b/manual/APPNOTE_011_Design_Investigation/submod_02.dot index 68266db9d..1a672c484 100644 --- a/manual/APPNOTE_011_Design_Investigation/submod_02.dot +++ b/manual/APPNOTE_011_Design_Investigation/submod_02.dot @@ -30,4 +30,4 @@ n8:e -> c17:p12:w [color="black", style="setlinewidth(3)", label=""]; n9:e -> x0:s0:w [color="black", label=""]; n9:e -> x1:s0:w [color="black", label=""]; n9:e -> x2:s0:w [color="black", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/submod_03.dot b/manual/APPNOTE_011_Design_Investigation/submod_03.dot index 92ef57599..0dbbe3baa 100644 --- a/manual/APPNOTE_011_Design_Investigation/submod_03.dot +++ b/manual/APPNOTE_011_Design_Investigation/submod_03.dot @@ -23,4 +23,4 @@ x1:s1:e -> n5:w [color="black", style="setlinewidth(3)", label=""]; n6:e -> x2:s1:w [color="black", style="setlinewidth(3)", label=""]; n7:e -> x2:s0:w [color="black", style="setlinewidth(3)", label=""]; v0:e -> c13:p8:w [color="black", style="setlinewidth(3)", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/sumprod_00.dot b/manual/APPNOTE_011_Design_Investigation/sumprod_00.dot index 6f9b7d3d6..06522dcc9 100644 --- a/manual/APPNOTE_011_Design_Investigation/sumprod_00.dot +++ b/manual/APPNOTE_011_Design_Investigation/sumprod_00.dot @@ -15,4 +15,4 @@ c4:p3:e -> v2:w [color="black", style="setlinewidth(3)", label=""]; v3:e -> c5:p1:w [color="black", style="setlinewidth(3)", label=""]; v4:e -> c5:p2:w [color="black", style="setlinewidth(3)", label=""]; c5:p3:e -> v5:w [color="black", style="setlinewidth(3)", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/sumprod_01.dot b/manual/APPNOTE_011_Design_Investigation/sumprod_01.dot index d0252270d..aefe7a6da 100644 --- a/manual/APPNOTE_011_Design_Investigation/sumprod_01.dot +++ b/manual/APPNOTE_011_Design_Investigation/sumprod_01.dot @@ -12,4 +12,4 @@ n2:e -> c9:p6:w [color="black", style="setlinewidth(3)", label=""]; n3:e -> c9:p7:w [color="black", style="setlinewidth(3)", label=""]; n4:e -> c10:p7:w [color="black", style="setlinewidth(3)", label=""]; c10:p8:e -> n5:w [color="black", style="setlinewidth(3)", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/sumprod_02.dot b/manual/APPNOTE_011_Design_Investigation/sumprod_02.dot index af87651b0..4646c9947 100644 --- a/manual/APPNOTE_011_Design_Investigation/sumprod_02.dot +++ b/manual/APPNOTE_011_Design_Investigation/sumprod_02.dot @@ -2,4 +2,4 @@ digraph "sumprod" { rankdir="LR"; remincross=true; n1 [ shape=octagon, label="prod", color="black", fontcolor="black" ]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/sumprod_03.dot b/manual/APPNOTE_011_Design_Investigation/sumprod_03.dot index 211551356..dcfea2b56 100644 --- a/manual/APPNOTE_011_Design_Investigation/sumprod_03.dot +++ b/manual/APPNOTE_011_Design_Investigation/sumprod_03.dot @@ -8,4 +8,4 @@ c5 [ shape=record, label="{{ A| B}|$4\n$mul|{ Y}}" ]; c5:p4:e -> n1:w [color="black", style="setlinewidth(3)", label=""]; v0:e -> c5:p2:w [color="black", style="setlinewidth(3)", label=""]; v1:e -> c5:p3:w [color="black", style="setlinewidth(3)", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/sumprod_04.dot b/manual/APPNOTE_011_Design_Investigation/sumprod_04.dot index 5223577e0..e77c41aa2 100644 --- a/manual/APPNOTE_011_Design_Investigation/sumprod_04.dot +++ b/manual/APPNOTE_011_Design_Investigation/sumprod_04.dot @@ -8,4 +8,4 @@ n1 [ shape=diamond, label="$3_Y" ]; n1:e -> c7:p4:w [color="black", style="setlinewidth(3)", label=""]; n2:e -> c7:p5:w [color="black", style="setlinewidth(3)", label=""]; c7:p6:e -> n3:w [color="black", style="setlinewidth(3)", label=""]; -}; +} diff --git a/manual/APPNOTE_011_Design_Investigation/sumprod_05.dot b/manual/APPNOTE_011_Design_Investigation/sumprod_05.dot index 45d001343..b54441290 100644 --- a/manual/APPNOTE_011_Design_Investigation/sumprod_05.dot +++ b/manual/APPNOTE_011_Design_Investigation/sumprod_05.dot @@ -12,4 +12,4 @@ n2:e -> c8:p5:w [color="black", style="setlinewidth(3)", label=""]; c8:p6:e -> n3:w [color="black", style="setlinewidth(3)", label=""]; v0:e -> c7:p4:w [color="black", style="setlinewidth(3)", label=""]; v1:e -> c7:p5:w [color="black", style="setlinewidth(3)", label=""]; -}; +} From 74d70bf9e9ea57d1684883c590251b82018f6f4e Mon Sep 17 00:00:00 2001 From: Fabien Marteau Date: Sun, 7 Dec 2014 19:04:06 +0100 Subject: [PATCH 134/492] manual/presentation.tex: bg option is unknown with beamer 3.3 in beamercolorbox --- manual/presentation.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/presentation.tex b/manual/presentation.tex index ee96253a0..dc5127755 100644 --- a/manual/presentation.tex +++ b/manual/presentation.tex @@ -74,7 +74,7 @@ {\usebeamerfont{subsection name}\usebeamercolor[fg]{subsection name}of \sectionname~\insertsectionnumber} \vskip1em\par \setbeamercolor{graybox}{bg=gray} -\begin{beamercolorbox}[sep=8pt,center,bg=gray]{graybox} +\begin{beamercolorbox}[sep=8pt,center]{graybox} \usebeamerfont{subsection title}\insertsection\par \end{beamercolorbox} \end{centering}} From fad9cec47b3aa9fc3d413abee92cc8380d0c0dc4 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 8 Dec 2014 10:43:38 +0100 Subject: [PATCH 135/492] Added $_DFFE_??_ cell types --- kernel/celltypes.h | 4 ++++ kernel/rtlil.cc | 5 +++++ techlibs/common/simcells.v | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 3d9e4cf93..f58ae14c4 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -156,6 +156,10 @@ struct CellTypes for (auto c1 : list_np) setup_type(stringf("$_DFF_%c_", c1), {"\\C", "\\D"}, {"\\Q"}); + for (auto c1 : list_np) + for (auto c2 : list_np) + setup_type(stringf("$_DFFE_%c%c_", c1, c2), {"\\C", "\\D", "\\E"}, {"\\Q"}); + for (auto c1 : list_np) for (auto c2 : list_np) for (auto c3 : list_01) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 803d783af..321c39e10 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -892,6 +892,11 @@ namespace { if (cell->type == "$_DFF_N_") { check_gate("DQC"); return; } if (cell->type == "$_DFF_P_") { check_gate("DQC"); return; } + if (cell->type == "$_DFFE_NN_") { check_gate("DQCE"); return; } + if (cell->type == "$_DFFE_NP_") { check_gate("DQCE"); return; } + if (cell->type == "$_DFFE_PN_") { check_gate("DQCE"); return; } + if (cell->type == "$_DFFE_PP_") { check_gate("DQCE"); return; } + if (cell->type == "$_DFF_NN0_") { check_gate("DQCR"); return; } if (cell->type == "$_DFF_NN1_") { check_gate("DQCR"); return; } if (cell->type == "$_DFF_NP0_") { check_gate("DQCR"); return; } diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v index 88566411a..eb62d7830 100644 --- a/techlibs/common/simcells.v +++ b/techlibs/common/simcells.v @@ -163,6 +163,38 @@ always @(posedge C) begin end endmodule +module \$_DFFE_NN_ (D, Q, C, E); +input D, C, E; +output reg Q; +always @(negedge C) begin + if (!E) Q <= D; +end +endmodule + +module \$_DFFE_NP_ (D, Q, C, E); +input D, C, E; +output reg Q; +always @(negedge C) begin + if (E) Q <= D; +end +endmodule + +module \$_DFFE_PN_ (D, Q, C, E); +input D, C, E; +output reg Q; +always @(posedge C) begin + if (!E) Q <= D; +end +endmodule + +module \$_DFFE_PP_ (D, Q, C, E); +input D, C, E; +output reg Q; +always @(posedge C) begin + if (E) Q <= D; +end +endmodule + module \$_DFF_NN0_ (D, Q, C, R); input D, C, R; output reg Q; From f1764b4fe99807c445526774563a98224b642766 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 8 Dec 2014 10:50:19 +0100 Subject: [PATCH 136/492] Added $dffe cell type --- kernel/rtlil.cc | 11 +++++++++++ passes/techmap/simplemap.cc | 23 +++++++++++++++++++++++ techlibs/common/simlib.v | 19 +++++++++++++++++++ techlibs/common/techmap.v | 2 +- 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 321c39e10..b1bf43941 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -752,6 +752,17 @@ namespace { return; } + if (cell->type == "$dffe") { + param_bool("\\CLK_POLARITY"); + param_bool("\\EN_POLARITY"); + port("\\CLK", 1); + port("\\EN", 1); + port("\\D", param("\\WIDTH")); + port("\\Q", param("\\WIDTH")); + check_expected(); + return; + } + if (cell->type == "$dffsr") { param_bool("\\CLK_POLARITY"); param_bool("\\SET_POLARITY"); diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index c3ca29e50..2dcb5f3eb 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -302,6 +302,28 @@ static void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell) } } +static void simplemap_dffe(RTLIL::Module *module, RTLIL::Cell *cell) +{ + int width = cell->parameters.at("\\WIDTH").as_int(); + char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N'; + char en_pol = cell->parameters.at("\\EN_POLARITY").as_bool() ? 'P' : 'N'; + + RTLIL::SigSpec sig_clk = cell->getPort("\\CLK"); + RTLIL::SigSpec sig_en = cell->getPort("\\EN"); + RTLIL::SigSpec sig_d = cell->getPort("\\D"); + RTLIL::SigSpec sig_q = cell->getPort("\\Q"); + + std::string gate_type = stringf("$_DFFE_%c%c_", clk_pol, en_pol); + + for (int i = 0; i < width; i++) { + RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); + gate->setPort("\\C", sig_clk); + gate->setPort("\\E", sig_en); + gate->setPort("\\D", sig_d[i]); + gate->setPort("\\Q", sig_q[i]); + } +} + static void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell) { int width = cell->parameters.at("\\WIDTH").as_int(); @@ -399,6 +421,7 @@ void simplemap_get_mappers(std::map Date: Mon, 8 Dec 2014 10:56:43 +0100 Subject: [PATCH 137/492] Added more documentation fixmes for nontrivial register cells --- manual/CHAPTER_CellLib.tex | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/manual/CHAPTER_CellLib.tex b/manual/CHAPTER_CellLib.tex index 64d3633e9..c12d8734e 100644 --- a/manual/CHAPTER_CellLib.tex +++ b/manual/CHAPTER_CellLib.tex @@ -357,7 +357,7 @@ Add a brief description of the {\tt \$fsm} cell type. For gate level logic networks, fixed function single bit cells are used that do not provide any parameters. -Simulation models for these cells can be found in the file {\tt techlibs/common/stdcells\_sim.v} in the Yosys +Simulation models for these cells can be found in the file {\tt techlibs/common/simcells.v} in the Yosys source tree. \begin{table}[t] @@ -428,6 +428,14 @@ Add information about {\tt \$slice} and {\tt \$concat} cells. Add information about {\tt \$alu}, {\tt \$macc}, {\tt \$fa}, and {\tt \$lcu} cells. \end{fixme} +\begin{fixme} +Add information about {\tt \$dffe}, {\tt \$dffsr}, {\tt \$dlatch}, and {\tt \$dlatchsr} cells. +\end{fixme} + +\begin{fixme} +Add information about {\tt \$\_DFFE\_??\_}, {\tt \$\_DFFSR\_???\_}, {\tt \$\_DLATCH\_?\_}, and {\tt \$\_DLATCHSR\_???\_} cells. +\end{fixme} + \begin{fixme} Add information about {\tt \$\_NAND\_}, {\tt \$\_NOR\_}, {\tt \$\_XNOR\_}, {\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, and {\tt \$\_OAI4\_} cells. \end{fixme} From 97487fee320b57356c810daaf2c6cb38e8576030 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 8 Dec 2014 14:10:52 +0100 Subject: [PATCH 138/492] Added skeleton dff2dffe pass --- passes/techmap/Makefile.inc | 1 + passes/techmap/alumacc.cc | 4 +- passes/techmap/dff2dffe.cc | 75 +++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 passes/techmap/dff2dffe.cc diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 56083ed2b..773a099ac 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -10,6 +10,7 @@ OBJS += passes/techmap/hilomap.o OBJS += passes/techmap/extract.o OBJS += passes/techmap/maccmap.o OBJS += passes/techmap/alumacc.o +OBJS += passes/techmap/dff2dffe.o endif GENFILES += passes/techmap/techmap.inc diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc index 03174ea04..2e297a2c6 100644 --- a/passes/techmap/alumacc.cc +++ b/passes/techmap/alumacc.cc @@ -538,8 +538,8 @@ struct AlumaccPass : public Pass { log("\n"); log(" alumacc [selection]\n"); log("\n"); - log("This pass translates arithmetic operations $add, $mul, $lt, etc. to $alu and\n"); - log("$macc cells.\n"); + log("This pass translates arithmetic operations like $add, $mul, $lt, etc. to $alu\n"); + log("and $macc cells.\n"); log("\n"); } virtual void execute(std::vector args, RTLIL::Design *design) diff --git a/passes/techmap/dff2dffe.cc b/passes/techmap/dff2dffe.cc new file mode 100644 index 000000000..6a1261f43 --- /dev/null +++ b/passes/techmap/dff2dffe.cc @@ -0,0 +1,75 @@ +/* + * 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 + +struct Dff2dffeWorker +{ + RTLIL::Module *module; + SigMap sigmap; + + Dff2dffeWorker(RTLIL::Module *module) : module(module), sigmap(module) + { + } + + void run() + { + log("Transforming $dff to $dffe cells in module %s:\n", log_id(module)); + } +}; + +struct Dff2dffePass : public Pass { + Dff2dffePass() : Pass("dff2dffe", "transform $dff cells to $dffe cells") { } + virtual void help() + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" dff2dffe [selection]\n"); + log("\n"); + log("This pass transforms $dff cells driven by a tree of multiplexers with one or\n"); + log("more feedback paths to a $dffe cells.\n"); + log("\n"); + } + virtual void execute(std::vector args, RTLIL::Design *design) + { + log_header("Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + // if (args[argidx] == "-foobar") { + // foobar_mode = true; + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto mod : design->selected_modules()) + if (!mod->has_processes_warn()) { + Dff2dffeWorker worker(mod); + worker.run(); + } + } +} Dff2dffePass; + +PRIVATE_NAMESPACE_END From bca2442c671b8ae0b8a8b933f6a27593dd13a168 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 8 Dec 2014 14:59:38 +0100 Subject: [PATCH 139/492] Added module->addDffe() and module->addDffeGate() --- kernel/rtlil.cc | 25 ++++++++++++++++++++++++- kernel/rtlil.h | 2 ++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index b1bf43941..2f2f7c704 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1595,7 +1595,7 @@ RTLIL::Cell* RTLIL::Module::addSr(RTLIL::IdString name, RTLIL::SigSpec sig_set, return cell; } -RTLIL::Cell* RTLIL::Module::addDff(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity) +RTLIL::Cell* RTLIL::Module::addDff(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity) { RTLIL::Cell *cell = addCell(name, "$dff"); cell->parameters["\\CLK_POLARITY"] = clk_polarity; @@ -1606,6 +1606,19 @@ RTLIL::Cell* RTLIL::Module::addDff(RTLIL::IdString name, RTLIL::SigSpec sig_clk, return cell; } +RTLIL::Cell* RTLIL::Module::addDffe(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool en_polarity) +{ + RTLIL::Cell *cell = addCell(name, "$dffe"); + cell->parameters["\\CLK_POLARITY"] = clk_polarity; + cell->parameters["\\EN_POLARITY"] = en_polarity; + cell->parameters["\\WIDTH"] = sig_q.size(); + cell->setPort("\\CLK", sig_clk); + cell->setPort("\\EN", sig_en); + cell->setPort("\\D", sig_d); + cell->setPort("\\Q", sig_q); + return cell; +} + RTLIL::Cell* RTLIL::Module::addDffsr(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity) { @@ -1673,6 +1686,16 @@ RTLIL::Cell* RTLIL::Module::addDffGate(RTLIL::IdString name, RTLIL::SigSpec sig_ return cell; } +RTLIL::Cell* RTLIL::Module::addDffeGate(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool en_polarity) +{ + RTLIL::Cell *cell = addCell(name, stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); + cell->setPort("\\C", sig_clk); + cell->setPort("\\E", sig_en); + cell->setPort("\\D", sig_d); + cell->setPort("\\Q", sig_q); + return cell; +} + RTLIL::Cell* RTLIL::Module::addDffsrGate(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity) { diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 0bb1e4e84..a488d3a6b 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -701,6 +701,7 @@ public: RTLIL::Cell* addSr (RTLIL::IdString name, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, RTLIL::SigSpec sig_q, bool set_polarity = true, bool clr_polarity = true); RTLIL::Cell* addDff (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity = true); + RTLIL::Cell* addDffe (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity = true, bool en_polarity = true); RTLIL::Cell* addDffsr (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity = true, bool set_polarity = true, bool clr_polarity = true); RTLIL::Cell* addAdff (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_arst, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, @@ -723,6 +724,7 @@ public: RTLIL::Cell* addOai4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, RTLIL::SigBit sig_y); RTLIL::Cell* addDffGate (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity = true); + RTLIL::Cell* addDffeGate (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity = true, bool en_polarity = true); RTLIL::Cell* addDffsrGate (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity = true, bool set_polarity = true, bool clr_polarity = true); RTLIL::Cell* addAdffGate (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_arst, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, From 7d6e586df8128d4265499ef3f61c1a85ff3cc02a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 8 Dec 2014 15:08:02 +0100 Subject: [PATCH 140/492] Added bool constructors to SigBit and SigSpec --- kernel/rtlil.cc | 10 ++++++++++ kernel/rtlil.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 2f2f7c704..f5dbafe16 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2188,6 +2188,16 @@ RTLIL::SigSpec::SigSpec(std::set bits) check(); } +RTLIL::SigSpec::SigSpec(bool bit) +{ + cover("kernel.rtlil.sigspec.init.bool"); + + width_ = 0; + hash_ = 0; + append_bit(bit); + check(); +} + void RTLIL::SigSpec::pack() const { RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index a488d3a6b..0157f3b7c 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -899,6 +899,7 @@ struct RTLIL::SigBit SigBit() : wire(NULL), data(RTLIL::State::S0) { } SigBit(RTLIL::State bit) : wire(NULL), data(bit) { } + SigBit(bool bit) : wire(NULL), data(bit ? RTLIL::S1 : RTLIL::S0) { } SigBit(RTLIL::Wire *wire) : wire(wire), offset(0) { log_assert(wire && wire->width == 1); } SigBit(RTLIL::Wire *wire, int offset) : wire(wire), offset(offset) { log_assert(wire != nullptr); } SigBit(const RTLIL::SigChunk &chunk) : wire(chunk.wire) { log_assert(chunk.width == 1); if (wire) offset = chunk.offset; else data = chunk.data[0]; } @@ -982,6 +983,7 @@ public: SigSpec(std::vector chunks); SigSpec(std::vector bits); SigSpec(std::set bits); + SigSpec(bool bit); SigSpec(RTLIL::SigSpec &&other) { width_ = other.width_; From 032511fac854cd0507dc84242bb55508c4757441 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 8 Dec 2014 15:38:58 +0100 Subject: [PATCH 141/492] Added functionality to dff2dffe pass --- kernel/celltypes.h | 1 + passes/techmap/dff2dffe.cc | 169 ++++++++++++++++++++++++++++++++++++- 2 files changed, 168 insertions(+), 2 deletions(-) diff --git a/kernel/celltypes.h b/kernel/celltypes.h index f58ae14c4..5ba4dd88b 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -116,6 +116,7 @@ struct CellTypes { setup_type("$sr", {"\\SET", "\\CLR"}, {"\\Q"}); setup_type("$dff", {"\\CLK", "\\D"}, {"\\Q"}); + setup_type("$dffe", {"\\CLK", "\\EN", "\\D"}, {"\\Q"}); setup_type("$dffsr", {"\\CLK", "\\SET", "\\CLR", "\\D"}, {"\\Q"}); setup_type("$adff", {"\\CLK", "\\ARST", "\\D"}, {"\\Q"}); setup_type("$dlatch", {"\\EN", "\\D"}, {"\\Q"}); diff --git a/passes/techmap/dff2dffe.cc b/passes/techmap/dff2dffe.cc index 6a1261f43..74f31f140 100644 --- a/passes/techmap/dff2dffe.cc +++ b/passes/techmap/dff2dffe.cc @@ -19,6 +19,7 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" +#include "kernel/celltypes.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -27,14 +28,178 @@ struct Dff2dffeWorker { RTLIL::Module *module; SigMap sigmap; + CellTypes ct; - Dff2dffeWorker(RTLIL::Module *module) : module(module), sigmap(module) + typedef std::pair cell_int_t; + std::map bit2mux; + std::vector dff_cells; + std::map bitusers; + + typedef std::map pattern_t; + typedef std::set patterns_t; + + Dff2dffeWorker(RTLIL::Module *module) : module(module), sigmap(module), ct(module->design) { + for (auto wire : module->wires()) { + if (wire->port_output) + for (auto bit : sigmap(wire)) + bitusers[bit]++; + } + + for (auto cell : module->cells()) { + if (cell->type == "$mux" || cell->type == "$pmux") { + RTLIL::SigSpec sig_y = sigmap(cell->getPort("\\Y")); + for (int i = 0; i < GetSize(sig_y); i++) + bit2mux[sig_y[i]] = cell_int_t(cell, i); + } + if (cell->type == "$dff") + dff_cells.push_back(cell); + for (auto conn : cell->connections()) { + if (ct.cell_output(cell->type, conn.first)) + continue; + for (auto bit : sigmap(conn.second)) + bitusers[bit]++; + } + } + } + + patterns_t find_muxtree_feedback_patterns(RTLIL::SigBit d, RTLIL::SigBit q, pattern_t path) + { + patterns_t ret; + + if (d == q) { + ret.insert(path); + return ret; + } + + if (bit2mux.count(d) == 0 || bitusers[d] > 1) + return ret; + + cell_int_t mux_cell_int = bit2mux.at(d); + RTLIL::SigSpec sig_a = sigmap(mux_cell_int.first->getPort("\\A")); + RTLIL::SigSpec sig_b = sigmap(mux_cell_int.first->getPort("\\B")); + RTLIL::SigSpec sig_s = sigmap(mux_cell_int.first->getPort("\\S")); + int width = GetSize(sig_a), index = mux_cell_int.second; + + for (int i = 0; i < GetSize(sig_s); i++) + if (path.count(sig_s[i]) && path.at(sig_s[i])) + { + ret = find_muxtree_feedback_patterns(sig_b[i*width + index], q, path); + + if (sig_b[i*width + index] == q) { + RTLIL::SigSpec s = mux_cell_int.first->getPort("\\B"); + s[i*width + index] = RTLIL::Sx; + mux_cell_int.first->setPort("\\B", s); + } + + return ret; + } + + pattern_t path_else = path; + + for (int i = 0; i < GetSize(sig_s); i++) + { + if (path.count(sig_s[i])) + continue; + + pattern_t path_this = path; + path_else[sig_s[i]] = false; + path_this[sig_s[i]] = true; + + for (auto &pat : find_muxtree_feedback_patterns(sig_b[i*width + index], q, path_this)) + ret.insert(pat); + + if (sig_b[i*width + index] == q) { + RTLIL::SigSpec s = mux_cell_int.first->getPort("\\B"); + s[i*width + index] = RTLIL::Sx; + mux_cell_int.first->setPort("\\B", s); + } + } + + for (auto &pat : find_muxtree_feedback_patterns(sig_a[index], q, path_else)) + ret.insert(pat); + + if (sig_a[index] == q) { + RTLIL::SigSpec s = mux_cell_int.first->getPort("\\A"); + s[index] = RTLIL::Sx; + mux_cell_int.first->setPort("\\A", s); + } + + return ret; + } + + void simplify_patterns(patterns_t&) + { + // TBD + } + + RTLIL::SigSpec make_patterns_logic(patterns_t patterns) + { + RTLIL::SigSpec or_input; + for (auto pat : patterns) { + RTLIL::SigSpec s1, s2; + for (auto it : pat) { + s1.append(it.first); + s2.append(it.second); + } + or_input.append(module->Ne(NEW_ID, s1, s2)); + } + if (GetSize(or_input) == 0) + return RTLIL::S1; + if (GetSize(or_input) == 1) + return or_input; + return module->ReduceOr(NEW_ID, or_input); + } + + void handle_dff_cell(RTLIL::Cell *dff_cell) + { + RTLIL::SigSpec sig_d = sigmap(dff_cell->getPort("\\D")); + RTLIL::SigSpec sig_q = sigmap(dff_cell->getPort("\\Q")); + + std::map> grouped_patterns; + std::set remaining_indices; + + for (int i = 0 ; i < GetSize(sig_d); i++) { + patterns_t patterns = find_muxtree_feedback_patterns(sig_d[i], sig_q[i], pattern_t()); + if (!patterns.empty()) { + simplify_patterns(patterns); + grouped_patterns[patterns].insert(i); + } else + remaining_indices.insert(i); + } + + for (auto &it : grouped_patterns) { + RTLIL::SigSpec new_sig_d, new_sig_q; + for (int i : it.second) { + new_sig_d.append(sig_d[i]); + new_sig_q.append(sig_q[i]); + } + RTLIL::Cell *new_cell = module->addDffe(NEW_ID, dff_cell->getPort("\\CLK"), make_patterns_logic(it.first), + new_sig_d, new_sig_q, dff_cell->getParam("\\CLK_POLARITY").as_bool(), true); + log(" created $dffe cell %s for %s -> %s.\n", log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q)); + } + + if (remaining_indices.empty()) { + log(" removing now obsolete cell %s.\n", log_id(dff_cell)); + module->remove(dff_cell); + } else if (GetSize(remaining_indices) != GetSize(sig_d)) { + log(" removing %d now obsolete bits from cell %s.\n", GetSize(sig_d) - GetSize(remaining_indices), log_id(dff_cell)); + RTLIL::SigSpec new_sig_d, new_sig_q; + for (int i : remaining_indices) { + new_sig_d.append(sig_d[i]); + new_sig_q.append(sig_q[i]); + } + dff_cell->setPort("\\D", new_sig_d); + dff_cell->setPort("\\Q", new_sig_q); + dff_cell->setParam("\\WIDTH", GetSize(remaining_indices)); + } } void run() { log("Transforming $dff to $dffe cells in module %s:\n", log_id(module)); + for (auto dff_cell : dff_cells) + handle_dff_cell(dff_cell); } }; @@ -47,7 +212,7 @@ struct Dff2dffePass : public Pass { log(" dff2dffe [selection]\n"); log("\n"); log("This pass transforms $dff cells driven by a tree of multiplexers with one or\n"); - log("more feedback paths to a $dffe cells.\n"); + log("more feedback paths to $dffe cells.\n"); log("\n"); } virtual void execute(std::vector args, RTLIL::Design *design) From 1282a113da11351dbac2b9df53e3e430d12def4a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 11 Dec 2014 13:56:20 +0100 Subject: [PATCH 142/492] Fixed supply0/supply1 with many wires --- frontends/verilog/verilog_parser.y | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 75af46522..621b6cc18 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -655,21 +655,33 @@ wire_decl: delete astbuf2; free_attr(albuf); } ';' | - attr TOK_SUPPLY0 TOK_ID ';' { + attr TOK_SUPPLY0 TOK_ID { ast_stack.back()->children.push_back(new AstNode(AST_WIRE)); ast_stack.back()->children.back()->str = *$3; append_attr(ast_stack.back()->children.back(), $1); ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, new AstNode(AST_IDENTIFIER), AstNode::mkconst_int(0, false, 1))); ast_stack.back()->children.back()->children[0]->str = *$3; delete $3; - } | - attr TOK_SUPPLY1 TOK_ID ';' { + } opt_supply_wires ';' | + attr TOK_SUPPLY1 TOK_ID { ast_stack.back()->children.push_back(new AstNode(AST_WIRE)); ast_stack.back()->children.back()->str = *$3; append_attr(ast_stack.back()->children.back(), $1); ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, new AstNode(AST_IDENTIFIER), AstNode::mkconst_int(1, false, 1))); ast_stack.back()->children.back()->children[0]->str = *$3; delete $3; + } opt_supply_wires ';'; + +opt_supply_wires: + /* empty */ | + opt_supply_wires ',' TOK_ID { + AstNode *wire_node = ast_stack.back()->children.at(GetSize(ast_stack.back()->children)-2)->clone(); + AstNode *assign_node = ast_stack.back()->children.at(GetSize(ast_stack.back()->children)-1)->clone(); + wire_node->str = *$3; + assign_node->children[0]->str = *$3; + ast_stack.back()->children.push_back(wire_node); + ast_stack.back()->children.push_back(assign_node); + delete $3; }; wire_name_list: From df52eedb3025c5250931c29c2417fbd0129500e1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 11 Dec 2014 15:27:38 +0100 Subject: [PATCH 143/492] Compile fix for visual studio --- libs/sha1/sha1.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/sha1/sha1.h b/libs/sha1/sha1.h index f6a03e735..9f526376e 100644 --- a/libs/sha1/sha1.h +++ b/libs/sha1/sha1.h @@ -23,6 +23,7 @@ #include #include +#include class SHA1 { From 7775d2806fe082626103f5abffd95fe9e1fccc27 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 11 Dec 2014 21:46:36 +0100 Subject: [PATCH 144/492] Added IdString::destruct_guard hack --- kernel/rtlil.cc | 1 + kernel/rtlil.h | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index f5dbafe16..5c010dabf 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -27,6 +27,7 @@ YOSYS_NAMESPACE_BEGIN +RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard; std::vector RTLIL::IdString::global_refcount_storage_; std::vector RTLIL::IdString::global_id_storage_; std::map RTLIL::IdString::global_id_index_; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 0157f3b7c..29fa90692 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -85,6 +85,12 @@ namespace RTLIL } }; + static struct destruct_guard_t { + bool ok = false; + destruct_guard_t() { ok = true; } + ~destruct_guard_t() { ok = false; } + } destruct_guard; + static std::vector global_refcount_storage_; static std::vector global_id_storage_; static std::map global_id_index_; @@ -98,6 +104,8 @@ namespace RTLIL static inline int get_reference(const char *p) { + log_assert(destruct_guard.ok); + if (p[0]) { log_assert(p[1] != 0); log_assert(p[0] == '$' || p[0] == '\\'); @@ -126,6 +134,11 @@ namespace RTLIL static inline void put_reference(int idx) { + // put_reference() may be called from destructors after the destructor of + // global_refcount_storage_ has been run. in this case we simply do nothing. + if (!destruct_guard.ok) + return; + log_assert(global_refcount_storage_.at(idx) > 0); if (--global_refcount_storage_.at(idx) != 0) From 6c768c686fb555683fba50a0c5e2713210346621 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 12 Dec 2014 11:34:25 +0100 Subject: [PATCH 145/492] Added missing prerequisites to README --- README | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README b/README index d90a11935..058208e9d 100644 --- a/README +++ b/README @@ -56,7 +56,8 @@ For example on Ubuntu Linux 14.04 LTS the following commands will install all prerequisites for building yosys: $ yosys_deps="build-essential clang bison flex libreadline-dev - tcl8.5-dev libffi-dev git mercurial graphviz xdot" + tcl8.5-dev libffi-dev git mercurial graphviz xdot + gawk pkg-config" $ sudo apt-get install $yosys_deps There are also pre-compiled packages for Yosys on Ubuntu. Visit the Yosys From 72f500c950f002a229d0434e76b24b347d7c583c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 12 Dec 2014 12:44:16 +0100 Subject: [PATCH 146/492] Removed UTF-8 chars from techmap.v --- techlibs/common/techmap.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index cb39fb4b2..7b5528560 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -207,7 +207,7 @@ module _90_lcu (P, G, CI, CO); g[0] = g[0] | (p[0] & CI); // [[CITE]] Brent Kung Adder - // R. P. Brent and H. T. Kung, “A Regular Layout for Parallel Adders”, + // R. P. Brent and H. T. Kung, "A Regular Layout for Parallel Adders", // IEEE Transaction on Computers, Vol. C-31, No. 3, p. 260-264, March, 1982 // Main tree From cf55371a22e33c1d476456129fdc8039ab9d0af8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 12 Dec 2014 12:49:46 +0100 Subject: [PATCH 147/492] Added psmisc to prerequisites --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 058208e9d..c731cac01 100644 --- a/README +++ b/README @@ -57,7 +57,7 @@ prerequisites for building yosys: $ yosys_deps="build-essential clang bison flex libreadline-dev tcl8.5-dev libffi-dev git mercurial graphviz xdot - gawk pkg-config" + gawk pkg-config psmics" $ sudo apt-get install $yosys_deps There are also pre-compiled packages for Yosys on Ubuntu. Visit the Yosys From f7cf60b45c04bcefd60cca3f56b648ddadd242ac Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 14 Dec 2014 17:24:44 +0100 Subject: [PATCH 148/492] Removed psmisc from deps list (usually fuser is already installed and the package name for it varies) --- README | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README b/README index c731cac01..5f34f3d0c 100644 --- a/README +++ b/README @@ -55,9 +55,8 @@ Xdot (graphviz) is used by the "show" command in yosys to display schematics. For example on Ubuntu Linux 14.04 LTS the following commands will install all prerequisites for building yosys: - $ yosys_deps="build-essential clang bison flex libreadline-dev - tcl8.5-dev libffi-dev git mercurial graphviz xdot - gawk pkg-config psmics" + $ yosys_deps="build-essential clang bison flex libreadline-dev gawk + tcl8.5-dev libffi-dev git mercurial graphviz xdot pkg-config" $ sudo apt-get install $yosys_deps There are also pre-compiled packages for Yosys on Ubuntu. Visit the Yosys From 32dce4a870e8f556897096a0c252b2e43f5622e5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 14 Dec 2014 17:37:46 +0100 Subject: [PATCH 149/492] Added "blif -unbuf" feature --- backends/blif/blif.cc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index 216e59fb5..18f76f7e4 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -40,6 +40,7 @@ struct BlifDumperConfig bool param_mode; std::string buf_type, buf_in, buf_out; + std::map> unbuf_types; std::string true_type, true_out, false_type, false_out; BlifDumperConfig() : icells_mode(false), conn_mode(false), impltf_mode(false), gates_mode(false), param_mode(false) { } @@ -146,6 +147,13 @@ struct BlifDumper { RTLIL::Cell *cell = cell_it.second; + if (config->unbuf_types.count(cell->type)) { + auto portnames = config->unbuf_types.at(cell->type); + f << stringf(".names %s %s\n1 1\n", + cstr(cell->getPort(portnames.first)), cstr(cell->getPort(portnames.second))); + continue; + } + if (!config->icells_mode && cell->type == "$_NOT_") { f << stringf(".names %s %s\n0 1\n", cstr(cell->getPort("\\A")), cstr(cell->getPort("\\Y"))); @@ -279,6 +287,10 @@ struct BlifBackend : public Backend { log(" -buf \n"); log(" use cells of type with the specified port names for buffers\n"); log("\n"); + log(" -unbuf \n"); + log(" replace buffer cells with the specified name and port names with\n"); + log(" a .names statement that models a buffer\n"); + log("\n"); log(" -true \n"); log(" -false \n"); log(" use the specified cell types to drive nets that are constant 1 or 0\n"); @@ -329,6 +341,13 @@ struct BlifBackend : public Backend { config.buf_out = args[++argidx]; continue; } + if (args[argidx] == "-unbuf" && argidx+3 < args.size()) { + RTLIL::IdString unbuf_type = RTLIL::escape_id(args[++argidx]); + RTLIL::IdString unbuf_in = RTLIL::escape_id(args[++argidx]); + RTLIL::IdString unbuf_out = RTLIL::escape_id(args[++argidx]); + config.unbuf_types[unbuf_type] = std::pair(unbuf_in, unbuf_out); + continue; + } if (args[argidx] == "-true" && argidx+2 < args.size()) { config.true_type = args[++argidx]; config.true_out = args[++argidx]; From 59d11978fc096734163731bb523a6d240ae1a41f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 14 Dec 2014 17:45:03 +0100 Subject: [PATCH 150/492] Added "write_blif -blackbox" based on code by Eddie Hung from https://github.com/eddiehung/yosys/commit/1e481661cb4a4 --- backends/blif/blif.cc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index 18f76f7e4..fa5f7bca2 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -38,12 +38,13 @@ struct BlifDumperConfig bool impltf_mode; bool gates_mode; bool param_mode; + bool blackbox_mode; std::string buf_type, buf_in, buf_out; std::map> unbuf_types; std::string true_type, true_out, false_type, false_out; - BlifDumperConfig() : icells_mode(false), conn_mode(false), impltf_mode(false), gates_mode(false), param_mode(false) { } + BlifDumperConfig() : icells_mode(false), conn_mode(false), impltf_mode(false), gates_mode(false), param_mode(false), blackbox_mode(false) { } }; struct BlifDumper @@ -130,6 +131,12 @@ struct BlifDumper } f << stringf("\n"); + if (module->get_bool_attribute("\\blackbox")) { + f << stringf(".blackbox\n"); + f << stringf(".end\n"); + return; + } + if (!config->impltf_mode) { if (!config->false_type.empty()) f << stringf(".%s %s %s=$false\n", subckt_or_gate(config->false_type), @@ -314,6 +321,9 @@ struct BlifBackend : public Backend { log(" -param\n"); log(" use the non-standard .param statement to write module parameters\n"); log("\n"); + log(" -blackbox\n"); + log(" write blackbox cells with .blackbox statement.\n"); + log("\n"); log(" -impltf\n"); log(" do not write definitions for the $true and $false wires.\n"); log("\n"); @@ -374,6 +384,10 @@ struct BlifBackend : public Backend { config.param_mode = true; continue; } + if (args[argidx] == "-blackbox") { + config.blackbox_mode = true; + continue; + } if (args[argidx] == "-impltf") { config.impltf_mode = true; continue; @@ -394,7 +408,7 @@ struct BlifBackend : public Backend { for (auto module_it : design->modules_) { RTLIL::Module *module = module_it.second; - if (module->get_bool_attribute("\\blackbox")) + if (module->get_bool_attribute("\\blackbox") && !config.blackbox_mode) continue; if (module->processes.size() != 0) From e01254d8244d16f98d6a99a2cd8c1692fe334dce Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 14 Dec 2014 18:00:38 +0100 Subject: [PATCH 151/492] Added "write_blif -undef" and support for special "-" true/false/undef type --- backends/blif/blif.cc | 46 +++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index fa5f7bca2..aaf85f460 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -42,7 +42,7 @@ struct BlifDumperConfig std::string buf_type, buf_in, buf_out; std::map> unbuf_types; - std::string true_type, true_out, false_type, false_out; + std::string true_type, true_out, false_type, false_out, undef_type, undef_out; BlifDumperConfig() : icells_mode(false), conn_mode(false), impltf_mode(false), gates_mode(false), param_mode(false), blackbox_mode(false) { } }; @@ -74,8 +74,11 @@ struct BlifDumper const char *cstr(RTLIL::SigBit sig) { - if (sig.wire == NULL) - return sig == RTLIL::State::S1 ? "$true" : "$false"; + if (sig.wire == NULL) { + if (sig == RTLIL::State::S0) return config->false_type == "-" ? config->false_out.c_str() : "$false"; + if (sig == RTLIL::State::S1) return config->true_type == "-" ? config->true_out.c_str() : "$true"; + return config->undef_type == "-" ? config->undef_out.c_str() : "$undef"; + } std::string str = RTLIL::unescape_id(sig.wire->name); for (size_t i = 0; i < str.size(); i++) @@ -138,16 +141,24 @@ struct BlifDumper } if (!config->impltf_mode) { - if (!config->false_type.empty()) - f << stringf(".%s %s %s=$false\n", subckt_or_gate(config->false_type), - config->false_type.c_str(), config->false_out.c_str()); - else + if (!config->false_type.empty()) { + if (config->false_type != "-") + f << stringf(".%s %s %s=$false\n", subckt_or_gate(config->false_type), + config->false_type.c_str(), config->false_out.c_str()); + } else f << stringf(".names $false\n"); - if (!config->true_type.empty()) - f << stringf(".%s %s %s=$true\n", subckt_or_gate(config->true_type), - config->true_type.c_str(), config->true_out.c_str()); - else + if (!config->true_type.empty()) { + if (config->true_type != "-") + f << stringf(".%s %s %s=$true\n", subckt_or_gate(config->true_type), + config->true_type.c_str(), config->true_out.c_str()); + } else f << stringf(".names $true\n1\n"); + if (!config->undef_type.empty()) { + if (config->undef_type != "-") + f << stringf(".%s %s %s=$undef\n", subckt_or_gate(config->undef_type), + config->undef_type.c_str(), config->undef_out.c_str()); + } else + f << stringf(".names $undef\n"); } for (auto &cell_it : module->cells_) @@ -300,7 +311,11 @@ struct BlifBackend : public Backend { log("\n"); log(" -true \n"); log(" -false \n"); - log(" use the specified cell types to drive nets that are constant 1 or 0\n"); + log(" -undef \n"); + log(" use the specified cell types to drive nets that are constant 1, 0, or\n"); + log(" undefined. when '-' is used as , then specifies\n"); + log(" the wire name to be used for the constant signal and no cell driving\n"); + log(" that wire is generated.\n"); log("\n"); log("The following options can be useful when the generated file is not going to be\n"); log("read by a BLIF parser but a custom tool. It is recommended to not name the output\n"); @@ -325,7 +340,7 @@ struct BlifBackend : public Backend { log(" write blackbox cells with .blackbox statement.\n"); log("\n"); log(" -impltf\n"); - log(" do not write definitions for the $true and $false wires.\n"); + 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) @@ -368,6 +383,11 @@ struct BlifBackend : public Backend { config.false_out = args[++argidx]; continue; } + if (args[argidx] == "-undef" && argidx+2 < args.size()) { + config.undef_type = args[++argidx]; + config.undef_out = args[++argidx]; + continue; + } if (args[argidx] == "-icells") { config.icells_mode = true; continue; From 6cec188c524f83a84e2cda88f0c121998867bc77 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 16 Dec 2014 10:38:25 +0100 Subject: [PATCH 152/492] Fixed build with gcc 4.6 --- kernel/rtlil.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 29fa90692..19996c8fc 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -86,7 +86,7 @@ namespace RTLIL }; static struct destruct_guard_t { - bool ok = false; + bool ok; // POD, will be initialized to zero destruct_guard_t() { ok = true; } ~destruct_guard_t() { ok = false; } } destruct_guard; From b95051fb709d1212abf4b3dad71204b15d6ff1db Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 17 Dec 2014 11:13:57 +0100 Subject: [PATCH 153/492] Fixed writing of $lut cells in BLIF backend --- backends/blif/blif.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index aaf85f460..366ed0369 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -227,14 +227,14 @@ struct BlifDumper log_assert(output.size() == 1); f << stringf(" %s", cstr(output)); f << stringf("\n"); - auto mask = cell->parameters.at("\\LUT").as_string(); - for (int i = 0; i < (1 << width); i++) { - if (mask[i] == '0') continue; - for (int j = width-1; j >= 0; j--) { - f << ((i>>j)&1 ? '1' : '0'); + RTLIL::SigSpec mask = cell->parameters.at("\\LUT"); + for (int i = 0; i < (1 << width); i++) + if (mask[i] == RTLIL::S1) { + for (int j = width-1; j >= 0; j--) { + f << ((i>>j)&1 ? '1' : '0'); + } + f << " 1\n"; } - f << stringf(" %c\n", mask[i]); - } continue; } From 30de490d867e4eaf9a7eb59ca85b976179b346ba Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 19 Dec 2014 17:54:44 +0100 Subject: [PATCH 154/492] Fixed another bug in write_blif handling of $lut cells --- backends/blif/blif.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index 366ed0369..6422d9f01 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -220,7 +220,7 @@ struct BlifDumper auto &inputs = cell->getPort("\\A"); auto width = cell->parameters.at("\\WIDTH").as_int(); log_assert(inputs.size() == width); - for (int i = 0; i < inputs.size(); i++) { + for (int i = width-1; i >= 0; i--) { f << stringf(" %s", cstr(inputs.extract(i, 1))); } auto &output = cell->getPort("\\Y"); From bacd3699b3ce75b716f8a233ca955fe188f8cbef Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 19 Dec 2014 18:47:19 +0100 Subject: [PATCH 155/492] Checking existence of ports in "hierarchy -check" --- passes/hierarchy/hierarchy.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index e070afdd5..028a0f0c2 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -199,6 +199,19 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check if (design->modules_.count(cell->type) == 0) log_error("File `%s' from libdir does not declare module `%s'.\n", filename.c_str(), cell->type.c_str()); did_something = true; + } else + if (flag_check) + { + RTLIL::Module *mod = design->module(cell->type); + for (auto &conn : cell->connections()) + if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') { + int id = atoi(conn.first.c_str()+1); + if (id < 0 || id >= GetSize(mod->ports)) + log_error("Module `%s' referenced in module `%s' in cell `%s' has only %d ports, requested port %d.\n", + log_id(cell->type), log_id(module), log_id(cell), GetSize(mod->ports), id + 1); + } else if (mod->wire(conn.first) == nullptr || mod->wire(conn.first)->port_id == 0) + log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a port named '%s'.\n", + log_id(cell->type), log_id(module), log_id(cell), log_id(conn.first)); } if (cell->parameters.size() == 0) From 5df192e71ce514d8b9bd2fa3bdee49dac8ee000d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 20 Dec 2014 00:03:20 +0100 Subject: [PATCH 156/492] Added $dffe support to write_verilog --- backends/verilog/verilog_backend.cc | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 7d08cc4e0..9e8342ab9 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -664,10 +664,10 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (cell->type == "$dff" || cell->type == "$adff") + if (cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffe") { - RTLIL::SigSpec sig_clk, sig_arst, val_arst; - bool pol_clk, pol_arst = false; + RTLIL::SigSpec sig_clk, sig_arst, sig_en, val_arst; + bool pol_clk, pol_arst = false, pol_en = false; sig_clk = cell->getPort("\\CLK"); pol_clk = cell->parameters["\\CLK_POLARITY"].as_bool(); @@ -678,6 +678,11 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) val_arst = RTLIL::SigSpec(cell->parameters["\\ARST_VALUE"]); } + if (cell->type == "$dffe") { + sig_en = cell->getPort("\\EN"); + pol_en = cell->parameters["\\EN_POLARITY"].as_bool(); + } + std::string reg_name = cellname(cell); bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name); @@ -702,6 +707,12 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) f << stringf("%s" " else\n", indent.c_str()); } + if (cell->type == "$dffe") { + f << stringf("%s" " if (%s", indent.c_str(), pol_en ? "" : "!"); + dump_sigspec(f, sig_en); + f << stringf(")\n"); + } + f << stringf("%s" " %s <= ", indent.c_str(), reg_name.c_str()); dump_cell_expr_port(f, cell, "D", false); f << stringf(";\n"); From f7b323196fbd1c2f35ab034b33f9617f7428cf31 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 20 Dec 2014 00:44:03 +0100 Subject: [PATCH 157/492] Added DFFE support to "abc" pass --- passes/abc/abc.cc | 89 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 78 insertions(+), 11 deletions(-) diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 9d6d94579..b1a96dda4 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -95,8 +95,8 @@ RTLIL::Module *module; std::vector signal_list; std::map signal_map; -bool clk_polarity; -RTLIL::SigSpec clk_sig; +bool clk_polarity, en_polarity; +RTLIL::SigSpec clk_sig, en_sig; int map_signal(RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1, int in2 = -1, int in3 = -1, int in4 = -1) { @@ -147,7 +147,24 @@ void extract_cell(RTLIL::Cell *cell, bool keepff) return; if (clk_sig != assign_map(cell->getPort("\\C"))) return; + goto matching_dff; + } + if (cell->type == "$_DFFE_NN_" || cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_") + { + if (clk_polarity != (cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_")) + return; + if (en_polarity != (cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PP_")) + return; + if (clk_sig != assign_map(cell->getPort("\\C"))) + return; + if (en_sig != assign_map(cell->getPort("\\E"))) + return; + goto matching_dff; + } + + if (0) { + matching_dff: RTLIL::SigSpec sig_d = cell->getPort("\\D"); RTLIL::SigSpec sig_q = cell->getPort("\\Q"); @@ -556,6 +573,9 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin clk_polarity = true; clk_sig = RTLIL::SigSpec(); + en_polarity = true; + en_sig = RTLIL::SigSpec(); + std::string tempdir_name = "/tmp/yosys-abc-XXXXXX"; if (!cleanup) tempdir_name[0] = tempdir_name[4] = '_'; @@ -607,6 +627,17 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin fclose(f); if (clk_str.empty()) { + if (clk_str.find(',') != std::string::npos) { + int pos = clk_str.find(','); + std::string en_str = clk_str.substr(pos+1); + clk_str = clk_str.substr(0, pos); + if (en_str[0] == '!') { + en_polarity = false; + en_str = en_str.substr(1); + } + if (module->wires_.count(RTLIL::escape_id(en_str)) != 0) + en_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(en_str)), 0)); + } if (clk_str[0] == '!') { clk_polarity = false; clk_str = clk_str.substr(1); @@ -618,19 +649,34 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (dff_mode && clk_sig.size() == 0) { int best_dff_counter = 0; - std::map, int> dff_counters; + typedef std::tuple clkdomain_t; + std::map dff_counters; for (auto &it : module->cells_) { RTLIL::Cell *cell = it.second; - if (cell->type != "$_DFF_N_" && cell->type != "$_DFF_P_") + clkdomain_t key; + + if (cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_") + { + key = clkdomain_t(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C")), true, RTLIL::SigSpec()); + } + else + if (cell->type == "$_DFFE_NN_" || cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_") + { + bool this_clk_pol = cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_"; + bool this_en_pol = cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PP_"; + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort("\\C")), this_en_pol, assign_map(cell->getPort("\\E"))); + } + else continue; - std::pair key(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C"))); if (++dff_counters[key] > best_dff_counter) { best_dff_counter = dff_counters[key]; - clk_polarity = key.first; - clk_sig = key.second; + clk_polarity = std::get<0>(key); + clk_sig = std::get<1>(key); + en_polarity = std::get<2>(key); + en_sig = std::get<3>(key); } } } @@ -638,13 +684,20 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (dff_mode || !clk_str.empty()) { if (clk_sig.size() == 0) log("No (matching) clock domain found. Not extracting any FF cells.\n"); - else - log("Found (matching) %s clock domain: %s\n", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); + else { + log("Found (matching) %s clock domain: %s", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); + if (en_sig.size() != 0) + log(", enabled by %s%s", en_polarity ? "" : "!", log_signal(en_sig)); + log("\n"); + } } if (clk_sig.size() != 0) mark_port(clk_sig); + if (en_sig.size() != 0) + mark_port(en_sig); + std::vector cells; cells.reserve(module->cells_.size()); for (auto &it : module->cells_) @@ -899,7 +952,14 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin } if (c->type == "\\DFF") { log_assert(clk_sig.size() == 1); - RTLIL::Cell *cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); + RTLIL::Cell *cell; + if (en_sig.size() == 0) { + cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); + } else { + log_assert(en_sig.size() == 1); + cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); + cell->setPort("\\E", en_sig); + } cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)])); cell->setPort("\\C", clk_sig); @@ -924,7 +984,14 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin } if (c->type == "\\_dff_") { log_assert(clk_sig.size() == 1); - RTLIL::Cell *cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); + RTLIL::Cell *cell; + if (en_sig.size() == 0) { + cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); + } else { + log_assert(en_sig.size() == 1); + cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); + cell->setPort("\\E", en_sig); + } cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)])); cell->setPort("\\C", clk_sig); From 25844b5683ab0d9a8ba5f4ee01bb5a601a1c8d24 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 21 Dec 2014 11:13:25 +0100 Subject: [PATCH 158/492] Fixed "abc" pass for clk and enable signals driven by logic --- passes/abc/abc.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index b1a96dda4..d38e538e3 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -147,6 +147,8 @@ void extract_cell(RTLIL::Cell *cell, bool keepff) return; if (clk_sig != assign_map(cell->getPort("\\C"))) return; + if (GetSize(en_sig) != 0) + return; goto matching_dff; } @@ -692,12 +694,6 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin } } - if (clk_sig.size() != 0) - mark_port(clk_sig); - - if (en_sig.size() != 0) - mark_port(en_sig); - std::vector cells; cells.reserve(module->cells_.size()); for (auto &it : module->cells_) @@ -714,6 +710,12 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin for (auto &cell_it : module->cells_) for (auto &port_it : cell_it.second->connections()) mark_port(port_it.second); + + if (clk_sig.size() != 0) + mark_port(clk_sig); + + if (en_sig.size() != 0) + mark_port(en_sig); handle_loops(); From 76fa5274927e8f960060938e10a042d85268a6ac Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 21 Dec 2014 16:52:05 +0100 Subject: [PATCH 159/492] Added support for multiple clock domains to "abc" pass --- kernel/rtlil.h | 1 + passes/abc/abc.cc | 187 ++++++++++++++++++++++++++++++---------------- 2 files changed, 124 insertions(+), 64 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 19996c8fc..efb8e833a 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1017,6 +1017,7 @@ public: inline const std::vector &bits() const { inline_unpack(); return bits_; } inline int size() const { return width_; } + inline bool empty() const { return width_ == 0; } inline RTLIL::SigBit &operator[](int index) { inline_unpack(); return bits_.at(index); } inline const RTLIL::SigBit &operator[](int index) const { inline_unpack(); return bits_.at(index); } diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index d38e538e3..5af9095f0 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -563,20 +563,24 @@ struct abc_output_filter void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, std::string liberty_file, std::string constr_file, bool cleanup, int lut_mode, bool dff_mode, std::string clk_str, - bool keepff, std::string delay_target, bool fast_mode) + bool keepff, std::string delay_target, bool fast_mode, const std::vector &cells) { module = current_module; map_autoidx = autoidx++; signal_map.clear(); signal_list.clear(); - assign_map.set(module); - clk_polarity = true; - clk_sig = RTLIL::SigSpec(); + if (clk_str != "$") + { + assign_map.set(module); - en_polarity = true; - en_sig = RTLIL::SigSpec(); + clk_polarity = true; + clk_sig = RTLIL::SigSpec(); + + en_polarity = true; + en_sig = RTLIL::SigSpec(); + } std::string tempdir_name = "/tmp/yosys-abc-XXXXXX"; if (!cleanup) @@ -628,7 +632,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin fprintf(f, "%s\n", abc_script.c_str()); fclose(f); - if (clk_str.empty()) { + if (!clk_str.empty() && clk_str != "$") + { if (clk_str.find(',') != std::string::npos) { int pos = clk_str.find(','); std::string en_str = clk_str.substr(pos+1); @@ -648,57 +653,21 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin clk_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(clk_str)), 0)); } - if (dff_mode && clk_sig.size() == 0) + if (dff_mode && clk_sig.empty()) + log_error("Clock domain %s not found.\n", clk_str.c_str()); + + if (dff_mode || !clk_str.empty()) { - int best_dff_counter = 0; - typedef std::tuple clkdomain_t; - std::map dff_counters; - - for (auto &it : module->cells_) - { - RTLIL::Cell *cell = it.second; - clkdomain_t key; - - if (cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_") - { - key = clkdomain_t(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C")), true, RTLIL::SigSpec()); - } - else - if (cell->type == "$_DFFE_NN_" || cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_") - { - bool this_clk_pol = cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_"; - bool this_en_pol = cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PP_"; - key = clkdomain_t(this_clk_pol, assign_map(cell->getPort("\\C")), this_en_pol, assign_map(cell->getPort("\\E"))); - } - else - continue; - - if (++dff_counters[key] > best_dff_counter) { - best_dff_counter = dff_counters[key]; - clk_polarity = std::get<0>(key); - clk_sig = std::get<1>(key); - en_polarity = std::get<2>(key); - en_sig = std::get<3>(key); - } - } - } - - if (dff_mode || !clk_str.empty()) { if (clk_sig.size() == 0) - log("No (matching) clock domain found. Not extracting any FF cells.\n"); + log("No%s clock domain found. Not extracting any FF cells.\n", clk_str.empty() ? "" : " matching"); else { - log("Found (matching) %s clock domain: %s", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); + log("Found%s %s clock domain: %s", clk_str.empty() ? "" : " matching", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); if (en_sig.size() != 0) log(", enabled by %s%s", en_polarity ? "" : "!", log_signal(en_sig)); log("\n"); } } - std::vector cells; - cells.reserve(module->cells_.size()); - for (auto &it : module->cells_) - if (design->selected(current_module, it.second)) - cells.push_back(it.second); for (auto c : cells) extract_cell(c, keepff); @@ -716,7 +685,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (en_sig.size() != 0) mark_port(en_sig); - + handle_loops(); std::string buffer = stringf("%s/input.blif", tempdir_name.c_str()); @@ -825,7 +794,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n", count_gates, GetSize(signal_list), count_input, count_output); log_push(); - + if (count_output > 0) { log_header("Executing ABC.\n"); @@ -1139,14 +1108,13 @@ struct AbcPass : public Pass { log(" generate netlist using luts of (max) the specified width.\n"); log("\n"); log(" -dff\n"); - log(" also pass $_DFF_?_ cells through ABC (only one clock domain, if many\n"); - log(" clock domains are present in a module, the one with the largest number\n"); - log(" of $_DFF_?_ cells in it is used)\n"); + log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n"); + log(" clock domains are automatically partitioned in clock domains and each\n"); + log(" domain is passed through ABC independently.\n"); log("\n"); - log(" -clk [!]\n"); - log(" use the specified clock domain. (when this option is used in combination\n"); - log(" with -dff, then it falls back to the automatic dection of clock domain\n"); - log(" if the specified clock is not found in a module.)\n"); + log(" -clk [!][,[!]]\n"); + log(" use only the specified clock domain. this is like -dff, but only FF\n"); + log(" cells that belong to the specified clock domain are used.\n"); log("\n"); log(" -keepff\n"); log(" set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n"); @@ -1228,6 +1196,7 @@ struct AbcPass : public Pass { } if (arg == "-clk" && argidx+1 < args.size()) { clk_str = args[++argidx]; + dff_mode = true; continue; } if (arg == "-keepff") { @@ -1247,12 +1216,102 @@ struct AbcPass : public Pass { if (!constr_file.empty() && liberty_file.empty()) log_cmd_error("Got -constr but no -liberty!\n"); - for (auto &mod_it : design->modules_) - if (design->selected(mod_it.second)) { - if (mod_it.second->processes.size() > 0) - log("Skipping module %s as it contains processes.\n", mod_it.second->name.c_str()); - else - abc_module(design, mod_it.second, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, dff_mode, clk_str, keepff, delay_target, fast_mode); + for (auto mod : design->selected_modules()) + if (mod->processes.size() > 0) + log("Skipping module %s as it contains processes.\n", log_id(mod)); + else if (!dff_mode || !clk_str.empty()) + abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, dff_mode, clk_str, keepff, delay_target, fast_mode, mod->selected_cells()); + else + { + assign_map.set(mod); + + std::vector all_cells = mod->selected_cells(); + std::set unassigned_cells(all_cells.begin(), all_cells.end()); + std::set expand_queue, next_expand_queue; + + typedef std::tuple clkdomain_t; + std::map> assigned_cells; + std::map assigned_cells_reverse; + + std::map> cell_to_bit; + std::map> bit_to_cell; + + for (auto cell : all_cells) + { + clkdomain_t key; + + for (auto &conn : cell->connections()) + for (auto bit : conn.second) { + bit = assign_map(bit); + if (bit.wire != nullptr) { + cell_to_bit[cell].insert(bit); + bit_to_cell[bit].insert(cell); + } + } + + if (cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_") + { + key = clkdomain_t(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C")), true, RTLIL::SigSpec()); + } + else + if (cell->type == "$_DFFE_NN_" || cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_") + { + bool this_clk_pol = cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_"; + bool this_en_pol = cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PP_"; + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort("\\C")), this_en_pol, assign_map(cell->getPort("\\E"))); + } + else + continue; + + unassigned_cells.erase(cell); + expand_queue.insert(cell); + + assigned_cells[key].push_back(cell); + assigned_cells_reverse[cell] = key; + } + + while (!expand_queue.empty()) + { + RTLIL::Cell *cell = *expand_queue.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue.erase(cell); + + for (auto bit : cell_to_bit.at(cell)) { + for (auto c : bit_to_cell[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + } + bit_to_cell[bit].clear(); + } + + if (expand_queue.empty()) + expand_queue.swap(next_expand_queue); + } + + clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); + for (auto cell : unassigned_cells) { + assigned_cells[key].push_back(cell); + assigned_cells_reverse[cell] = key; + } + + log_header("Summary of detected clock domains:\n"); + for (auto &it : assigned_cells) + log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), + std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), + std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); + + for (auto &it : assigned_cells) { + clk_polarity = std::get<0>(it.first); + clk_sig = assign_map(std::get<1>(it.first)); + en_polarity = std::get<2>(it.first); + en_sig = assign_map(std::get<3>(it.first)); + abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, + !clk_sig.empty(), "$", keepff, delay_target, fast_mode, it.second); + assign_map.set(mod); + } } assign_map.clear(); From a216df043374f3d3a699889f0bf207491df037ea Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 23 Dec 2014 12:29:02 +0100 Subject: [PATCH 160/492] Added "abc -markgroups" --- passes/abc/abc.cc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 5af9095f0..2be95ee94 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -89,6 +89,7 @@ struct gate_t RTLIL::SigBit bit; }; +bool markgroups; int map_autoidx; SigMap assign_map; RTLIL::Module *module; @@ -855,6 +856,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin for (auto &it : mapped_mod->wires_) { RTLIL::Wire *w = it.second; RTLIL::Wire *wire = module->addWire(remap_name(w->name)); + if (markgroups) wire->attributes["\\abcgroup"] = map_autoidx; design->select(module, wire); } @@ -880,6 +882,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin } if (c->type == "\\NOT") { RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_NOT_"); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)])); design->select(module, cell); @@ -887,6 +890,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin } if (c->type == "\\AND" || c->type == "\\OR" || c->type == "\\XOR" || c->type == "\\NAND" || c->type == "\\NOR" || c->type == "\\XNOR") { RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)])); @@ -895,6 +899,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin } if (c->type == "\\MUX") { RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX_"); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)])); @@ -904,6 +909,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin } if (c->type == "\\AOI3" || c->type == "\\OAI3") { RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)])); @@ -913,6 +919,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin } if (c->type == "\\AOI4" || c->type == "\\OAI4") { RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)])); @@ -931,6 +938,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); cell->setPort("\\E", en_sig); } + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)])); cell->setPort("\\C", clk_sig); @@ -963,6 +971,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); cell->setPort("\\E", en_sig); } + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)])); cell->setPort("\\C", clk_sig); @@ -970,6 +979,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin continue; } RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type); + if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; cell->parameters = c->parameters; for (auto &conn : c->connections()) { RTLIL::SigSpec newsig; @@ -1124,6 +1134,11 @@ struct AbcPass : public Pass { log(" when this option is used, the temporary files created by this pass\n"); log(" are not removed. this is useful for debugging.\n"); log("\n"); + log(" -markgroups\n"); + log(" set a 'abcgroup' attribute on all objects created by ABC. The value of\n"); + log(" this attribute is a unique integer for each ABC process started. This\n"); + log(" is usefull for debugging the partitioning of clock domains.\n"); + log("\n"); log("When neither -liberty nor -lut is used, the Yosys standard cell library is\n"); log("loaded into ABC before the ABC script is executed.\n"); log("\n"); @@ -1142,6 +1157,7 @@ struct AbcPass : public Pass { std::string script_file, liberty_file, constr_file, clk_str, delay_target; bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; int lut_mode = 0; + markgroups = false; #ifdef _WIN32 if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe")) @@ -1207,6 +1223,10 @@ struct AbcPass : public Pass { cleanup = false; continue; } + if (arg == "-markgroups") { + markgroups = true; + continue; + } break; } extra_args(args, argidx, design); From 4f5b97954e15b1aa40f7b3068865f4d8fcbe9fb7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 23 Dec 2014 12:29:29 +0100 Subject: [PATCH 161/492] Added "show -colorattr" --- passes/cmds/show.cc | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index 715c1de56..f61f195be 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -64,6 +64,10 @@ struct ShowWorker const std::vector> &color_selections; const std::vector> &label_selections; + std::map colorattr_cache; + RTLIL::IdString colorattr; + + static uint32_t xorshift32(uint32_t x) { x ^= x << 13; x ^= x >> 17; @@ -128,7 +132,25 @@ struct ShowWorker dot_escape_store.push_back(stringf(", color=\"%s\"", s.first.c_str())); return dot_escape_store.back().c_str(); } - return ""; + + RTLIL::Const colorattr_value; + RTLIL::Cell *cell = module->cell(member_name); + RTLIL::Wire *wire = module->wire(member_name); + + if (cell && cell->attributes.count(colorattr)) + colorattr_value = cell->attributes.at(colorattr); + else if (wire && wire->attributes.count(colorattr)) + colorattr_value = wire->attributes.at(colorattr); + else + return ""; + + if (colorattr_cache.count(colorattr_value) == 0) { + int next_id = GetSize(colorattr_cache); + colorattr_cache[colorattr_value] = (next_id % 8) + 1; + } + + dot_escape_store.push_back(stringf(", colorscheme=\"dark28\", color=\"%d\", fontcolor=\"%d\"", colorattr_cache.at(colorattr_value), colorattr_cache.at(colorattr_value))); + return dot_escape_store.back().c_str(); } const char *findLabel(std::string member_name) @@ -507,10 +529,10 @@ struct ShowWorker ShowWorker(FILE *f, RTLIL::Design *design, std::vector &libs, uint32_t colorSeed, bool genWidthLabels, bool genSignedLabels, bool stretchIO, bool enumerateIds, bool abbreviateIds, bool notitle, const std::vector> &color_selections, - const std::vector> &label_selections) : + const std::vector> &label_selections, RTLIL::IdString colorattr) : f(f), design(design), currentColor(colorSeed), genWidthLabels(genWidthLabels), genSignedLabels(genSignedLabels), stretchIO(stretchIO), enumerateIds(enumerateIds), abbreviateIds(abbreviateIds), - notitle(notitle), color_selections(color_selections), label_selections(label_selections) + notitle(notitle), color_selections(color_selections), label_selections(label_selections), colorattr(colorattr) { ct.setup_internals(); ct.setup_internals_mem(); @@ -586,6 +608,10 @@ struct ShowPass : public Pass { log(" for the random number generator. Change the seed value if the colored\n"); log(" graph still is ambigous. A seed of zero deactivates the coloring.\n"); log("\n"); + log(" -colorattr \n"); + log(" Use the specified attribute to assign colors. A unique color is\n"); + log(" assigned to each unique value of this attribute.\n"); + log("\n"); log(" -width\n"); log(" annotate busses with a label indicating the width of the bus.\n"); log("\n"); @@ -637,6 +663,7 @@ struct ShowPass : public Pass { bool flag_enum = false; bool flag_abbeviate = true; bool flag_notitle = false; + RTLIL::IdString colorattr; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -678,6 +705,10 @@ struct ShowPass : public Pass { colorSeed = ShowWorker::xorshift32(colorSeed); continue; } + if (arg == "-colorattr" && argidx+1 < args.size()) { + colorattr = RTLIL::escape_id(args[++argidx]); + continue; + } if (arg == "-format" && argidx+1 < args.size()) { format = args[++argidx]; continue; @@ -753,7 +784,7 @@ struct ShowPass : public Pass { delete lib; log_cmd_error("Can't open dot file `%s' for writing.\n", dot_file.c_str()); } - ShowWorker worker(f, design, libs, colorSeed, flag_width, flag_signed, flag_stretch, flag_enum, flag_abbeviate, flag_notitle, color_selections, label_selections); + ShowWorker worker(f, design, libs, colorSeed, flag_width, flag_signed, flag_stretch, flag_enum, flag_abbeviate, flag_notitle, color_selections, label_selections, colorattr); fclose(f); for (auto lib : libs) From 5fe02b79650331345462f6ae75f78ee334d70a83 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 23 Dec 2014 13:49:54 +0100 Subject: [PATCH 162/492] Indenting fix in show.cc --- passes/cmds/show.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index f61f195be..edc417c02 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -482,8 +482,8 @@ struct ShowWorker if (left_node[0] == 'x' && right_node[0] == 'x') { currentColor = xorshift32(currentColor); - fprintf(f, "%s:e -> %s:w [arrowhead=odiamond, arrowtail=odiamond, dir=both, %s, %s];\n", left_node.c_str(), right_node.c_str(), nextColor(conn).c_str(), widthLabel(conn.first.size()).c_str()); - } else { + fprintf(f, "%s:e -> %s:w [arrowhead=odiamond, arrowtail=odiamond, dir=both, %s, %s];\n", left_node.c_str(), right_node.c_str(), nextColor(conn).c_str(), widthLabel(conn.first.size()).c_str()); + } else { net_conn_map[right_node].bits = conn.first.size(); net_conn_map[right_node].color = nextColor(conn, net_conn_map[right_node].color); net_conn_map[left_node].bits = conn.first.size(); From 48ca1ff9ef5bba939348ceeec75ad310afd9fcf8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 23 Dec 2014 14:08:38 +0100 Subject: [PATCH 163/492] Improved ABC clock domain partitioning --- passes/abc/abc.cc | 61 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 2be95ee94..844d5783c 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -41,6 +41,7 @@ #include "kernel/register.h" #include "kernel/sigtools.h" +#include "kernel/celltypes.h" #include "kernel/cost.h" #include "kernel/log.h" #include @@ -1244,17 +1245,21 @@ struct AbcPass : public Pass { else { assign_map.set(mod); + CellTypes ct(design); std::vector all_cells = mod->selected_cells(); std::set unassigned_cells(all_cells.begin(), all_cells.end()); + std::set expand_queue, next_expand_queue; + std::set expand_queue_up, next_expand_queue_up; + std::set expand_queue_down, next_expand_queue_down; typedef std::tuple clkdomain_t; std::map> assigned_cells; std::map assigned_cells_reverse; - std::map> cell_to_bit; - std::map> bit_to_cell; + std::map> cell_to_bit, cell_to_bit_up, cell_to_bit_down; + std::map> bit_to_cell, bit_to_cell_up, bit_to_cell_down; for (auto cell : all_cells) { @@ -1266,6 +1271,14 @@ struct AbcPass : public Pass { if (bit.wire != nullptr) { cell_to_bit[cell].insert(bit); bit_to_cell[bit].insert(cell); + if (ct.cell_input(cell->type, conn.first)) { + cell_to_bit_up[cell].insert(bit); + bit_to_cell_down[bit].insert(cell); + } + if (ct.cell_output(cell->type, conn.first)) { + cell_to_bit_down[cell].insert(bit); + bit_to_cell_up[bit].insert(cell); + } } } @@ -1285,11 +1298,55 @@ struct AbcPass : public Pass { unassigned_cells.erase(cell); expand_queue.insert(cell); + expand_queue_up.insert(cell); + expand_queue_down.insert(cell); assigned_cells[key].push_back(cell); assigned_cells_reverse[cell] = key; } + while (!expand_queue_up.empty() || !expand_queue_down.empty()) + { + if (!expand_queue_up.empty()) + { + RTLIL::Cell *cell = *expand_queue_up.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue_up.erase(cell); + + for (auto bit : cell_to_bit_up[cell]) + for (auto c : bit_to_cell_up[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (!expand_queue_down.empty()) + { + RTLIL::Cell *cell = *expand_queue_down.begin(); + clkdomain_t key = assigned_cells_reverse.at(cell); + expand_queue_down.erase(cell); + + for (auto bit : cell_to_bit_down[cell]) + for (auto c : bit_to_cell_down[bit]) + if (unassigned_cells.count(c)) { + unassigned_cells.erase(c); + next_expand_queue_up.insert(c); + assigned_cells[key].push_back(c); + assigned_cells_reverse[c] = key; + expand_queue.insert(c); + } + } + + if (expand_queue_up.empty() && expand_queue_down.empty()) { + expand_queue_up.swap(next_expand_queue_up); + expand_queue_down.swap(next_expand_queue_down); + } + } + while (!expand_queue.empty()) { RTLIL::Cell *cell = *expand_queue.begin(); From edb3c9d0c4f0bc3a108ffebc01f02ff4d7354487 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 24 Dec 2014 09:51:17 +0100 Subject: [PATCH 164/492] Renamed extend() to extend_xx(), changed most users to extend_u0() --- backends/spice/spice.cc | 2 +- frontends/ast/genrtlil.cc | 2 +- kernel/rtlil.cc | 15 +++++++-------- kernel/rtlil.h | 2 +- passes/fsm/fsm_extract.cc | 2 +- passes/memory/memory_collect.cc | 24 ++++++++++++------------ passes/opt/opt_const.cc | 6 +++--- passes/proc/proc_arst.cc | 2 +- passes/sat/expose.cc | 2 +- passes/techmap/alumacc.cc | 2 +- passes/techmap/maccmap.cc | 6 +++--- passes/techmap/simplemap.cc | 2 +- 12 files changed, 33 insertions(+), 34 deletions(-) diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc index 390822ed3..2c614178b 100644 --- a/backends/spice/spice.cc +++ b/backends/spice/spice.cc @@ -84,7 +84,7 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De RTLIL::SigSpec sig(RTLIL::State::Sz, wire->width); if (cell->hasPort(wire->name)) { sig = sigmap(cell->getPort(wire->name)); - sig.extend(wire->width, false); + sig.extend_u0(wire->width, false); } port_sigs.push_back(sig); } diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 4a102370b..238da2634 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -73,7 +73,7 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_wi static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_signed) { if (width <= sig.size()) { - sig.extend(width, is_signed); + sig.extend_u0(width, is_signed); return; } diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 5c010dabf..0e8078df6 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2590,9 +2590,9 @@ void RTLIL::SigSpec::append_bit(const RTLIL::SigBit &bit) check(); } -void RTLIL::SigSpec::extend(int width, bool is_signed) +void RTLIL::SigSpec::extend_xx(int width, bool is_signed) { - cover("kernel.rtlil.sigspec.extend"); + cover("kernel.rtlil.sigspec.extend_xx"); pack(); @@ -2600,10 +2600,9 @@ void RTLIL::SigSpec::extend(int width, bool is_signed) remove(width, width_ - width); if (width_ < width) { - RTLIL::SigSpec padding = width_ > 0 ? extract(width_ - 1, 1) : RTLIL::SigSpec(RTLIL::State::S0); - if (!is_signed && padding != RTLIL::SigSpec(RTLIL::State::Sx) && padding != RTLIL::SigSpec(RTLIL::State::Sz) && - padding != RTLIL::SigSpec(RTLIL::State::Sa) && padding != RTLIL::SigSpec(RTLIL::State::Sm)) - padding = RTLIL::SigSpec(RTLIL::State::S0); + RTLIL::SigBit padding = width_ > 0 ? (*this)[width_ - 1] : RTLIL::State::S0; + if (!is_signed && (padding == RTLIL::State::S1 || padding.wire)) + padding = RTLIL::State::S0; while (width_ < width) append(padding); } @@ -2619,9 +2618,9 @@ void RTLIL::SigSpec::extend_u0(int width, bool is_signed) remove(width, width_ - width); if (width_ < width) { - RTLIL::SigSpec padding = width_ > 0 ? extract(width_ - 1, 1) : RTLIL::SigSpec(RTLIL::State::S0); + RTLIL::SigBit padding = width_ > 0 ? (*this)[width_ - 1] : RTLIL::State::S0; if (!is_signed) - padding = RTLIL::SigSpec(RTLIL::State::S0); + padding = RTLIL::State::S0; while (width_ < width) append(padding); } diff --git a/kernel/rtlil.h b/kernel/rtlil.h index efb8e833a..99831244e 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1057,7 +1057,7 @@ public: void append(const RTLIL::SigSpec &signal); void append_bit(const RTLIL::SigBit &bit); - void extend(int width, bool is_signed = false); + void extend_xx(int width, bool is_signed = false); void extend_u0(int width, bool is_signed = false); RTLIL::SigSpec repeat(int num) const; diff --git a/passes/fsm/fsm_extract.cc b/passes/fsm/fsm_extract.cc index e01c54969..68667ef02 100644 --- a/passes/fsm/fsm_extract.cc +++ b/passes/fsm/fsm_extract.cc @@ -40,7 +40,7 @@ static std::map> exclusive_ctrls; static bool find_states(RTLIL::SigSpec sig, const RTLIL::SigSpec &dff_out, RTLIL::SigSpec &ctrl, std::map &states, RTLIL::Const *reset_state = NULL) { - sig.extend(dff_out.size(), false); + sig.extend_u0(dff_out.size(), false); if (sig == dff_out) return true; diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc index 546306822..ccc196202 100644 --- a/passes/memory/memory_collect.cc +++ b/passes/memory/memory_collect.cc @@ -85,12 +85,12 @@ void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) RTLIL::SigSpec data = cell->getPort("\\DATA"); RTLIL::SigSpec en = cell->getPort("\\EN"); - clk.extend(1, false); - clk_enable.extend(1, false); - clk_polarity.extend(1, false); - addr.extend(addr_bits, false); - data.extend(memory->width, false); - en.extend(memory->width, false); + clk.extend_u0(1, false); + clk_enable.extend_u0(1, false); + clk_polarity.extend_u0(1, false); + addr.extend_u0(addr_bits, false); + data.extend_u0(memory->width, false); + en.extend_u0(memory->width, false); sig_wr_clk.append(clk); sig_wr_clk_enable.append(clk_enable); @@ -112,12 +112,12 @@ void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) RTLIL::SigSpec addr = cell->getPort("\\ADDR"); RTLIL::SigSpec data = cell->getPort("\\DATA"); - clk.extend(1, false); - clk_enable.extend(1, false); - clk_polarity.extend(1, false); - transparent.extend(1, false); - addr.extend(addr_bits, false); - data.extend(memory->width, false); + clk.extend_u0(1, false); + clk_enable.extend_u0(1, false); + clk_polarity.extend_u0(1, false); + transparent.extend_u0(1, false); + addr.extend_u0(addr_bits, false); + data.extend_u0(memory->width, false); sig_rd_clk.append(clk); sig_rd_clk_enable.append(clk_enable); diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc index 1e59f18c1..5bac76cf6 100644 --- a/passes/opt/opt_const.cc +++ b/passes/opt/opt_const.cc @@ -491,7 +491,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (a[i].wire == NULL && b[i].wire == NULL && a[i] != b[i] && a[i].data <= RTLIL::State::S1 && b[i].data <= RTLIL::State::S1) { cover_list("opt.opt_const.eqneq.isneq", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); RTLIL::SigSpec new_y = RTLIL::SigSpec((cell->type == "$eq" || cell->type == "$eqx") ? RTLIL::State::S0 : RTLIL::State::S1); - new_y.extend(cell->parameters["\\Y_WIDTH"].as_int(), false); + new_y.extend_u0(cell->parameters["\\Y_WIDTH"].as_int(), false); replace_cell(assign_map, module, cell, "isneq", "\\Y", new_y); goto next_cell; } @@ -504,7 +504,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (new_a.size() == 0) { cover_list("opt.opt_const.eqneq.empty", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); RTLIL::SigSpec new_y = RTLIL::SigSpec((cell->type == "$eq" || cell->type == "$eqx") ? RTLIL::State::S1 : RTLIL::State::S0); - new_y.extend(cell->parameters["\\Y_WIDTH"].as_int(), false); + new_y.extend_u0(cell->parameters["\\Y_WIDTH"].as_int(), false); replace_cell(assign_map, module, cell, "empty", "\\Y", new_y); goto next_cell; } @@ -560,7 +560,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons RTLIL::SigSpec sig_y(cell->type == "$shiftx" ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam("\\Y_WIDTH").as_int()); if (GetSize(sig_a) < GetSize(sig_y)) - sig_a.extend(GetSize(sig_y), cell->getParam("\\A_SIGNED").as_bool()); + sig_a.extend_u0(GetSize(sig_y), cell->getParam("\\A_SIGNED").as_bool()); for (int i = 0; i < GetSize(sig_y); i++) { int idx = i + shift_bits; diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index cd84cfd5b..0874d0981 100644 --- a/passes/proc/proc_arst.cc +++ b/passes/proc/proc_arst.cc @@ -262,7 +262,7 @@ struct ProcArstPass : public Pass { for (auto &chunk : act.first.chunks()) if (chunk.wire && chunk.wire->attributes.count("\\init")) { RTLIL::SigSpec value = chunk.wire->attributes.at("\\init"); - value.extend(chunk.wire->width, false); + value.extend_xx(chunk.wire->width, false); arst_sig.append(chunk); arst_val.append(value.extract(chunk.offset, chunk.width)); } diff --git a/passes/sat/expose.cc b/passes/sat/expose.cc index 46ebdb846..b012bc6a4 100644 --- a/passes/sat/expose.cc +++ b/passes/sat/expose.cc @@ -607,7 +607,7 @@ struct ExposePass : public Pass { RTLIL::SigSpec sig; if (cell->hasPort(p->name)) sig = cell->getPort(p->name); - sig.extend(w->width); + sig.extend_u0(w->width); if (w->port_input) module->connect(RTLIL::SigSig(sig, w)); else diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc index 2e297a2c6..dcffed94d 100644 --- a/passes/techmap/alumacc.cc +++ b/passes/techmap/alumacc.cc @@ -501,7 +501,7 @@ struct AlumaccWorker if (GetSize(sig) > 1) sig = module->ReduceOr(NEW_ID, sig); - sig.extend(GetSize(cmp_y)); + sig.extend_u0(GetSize(cmp_y)); module->connect(cmp_y, sig); } diff --git a/passes/techmap/maccmap.cc b/passes/techmap/maccmap.cc index c487cc36a..ffbd6289d 100644 --- a/passes/techmap/maccmap.cc +++ b/passes/techmap/maccmap.cc @@ -49,7 +49,7 @@ struct MaccmapWorker void add(RTLIL::SigSpec a, bool is_signed, bool do_subtract) { - a.extend(width, is_signed); + a.extend_u0(width, is_signed); if (do_subtract) { a = module->Not(NEW_ID, a); @@ -65,10 +65,10 @@ struct MaccmapWorker if (GetSize(a) < GetSize(b)) std::swap(a, b); - a.extend(width, is_signed); + a.extend_u0(width, is_signed); if (GetSize(b) > width) - b.extend(width, is_signed); + b.extend_u0(width, is_signed); for (int i = 0; i < GetSize(b); i++) if (is_signed && i+1 == GetSize(b)) diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index 2dcb5f3eb..c1c0f76a8 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -32,7 +32,7 @@ static void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell) RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_y = cell->getPort("\\Y"); - sig_a.extend(GetSize(sig_y), cell->parameters.at("\\A_SIGNED").as_bool()); + sig_a.extend_u0(GetSize(sig_y), cell->parameters.at("\\A_SIGNED").as_bool()); for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_"); From 4aa9fbbf3fe095220895dd2508ac6118b7382493 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 24 Dec 2014 10:49:24 +0100 Subject: [PATCH 165/492] Improvements in simplemap api, added $ne $nex $eq $eqx support --- passes/techmap/simplemap.cc | 81 ++++++++++++++++++++++++++----------- passes/techmap/simplemap.h | 48 ++++++++++++++++++++++ passes/techmap/techmap.cc | 4 +- techlibs/common/techmap.v | 54 +++---------------------- 4 files changed, 112 insertions(+), 75 deletions(-) create mode 100644 passes/techmap/simplemap.h diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index c1c0f76a8..694ebf226 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -17,17 +17,16 @@ * */ -#include "kernel/register.h" +#include "simplemap.h" #include "kernel/sigtools.h" -#include "kernel/log.h" #include #include #include USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN +YOSYS_NAMESPACE_BEGIN -static void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell) { RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_y = cell->getPort("\\Y"); @@ -41,7 +40,7 @@ static void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell) } } -static void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell) { RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_y = cell->getPort("\\Y"); @@ -51,7 +50,7 @@ static void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell) module->connect(RTLIL::SigSig(sig_y, sig_a)); } -static void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell) { RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_b = cell->getPort("\\B"); @@ -88,7 +87,7 @@ static void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell) } } -static void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell) { RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_y = cell->getPort("\\Y"); @@ -183,7 +182,7 @@ static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig) sig = RTLIL::SigSpec(0, 1); } -static void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell) { RTLIL::SigSpec sig_a = cell->getPort("\\A"); logic_reduce(module, sig_a); @@ -203,7 +202,7 @@ static void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell) gate->setPort("\\Y", sig_y); } -static void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell) { RTLIL::SigSpec sig_a = cell->getPort("\\A"); logic_reduce(module, sig_a); @@ -232,7 +231,31 @@ static void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell) gate->setPort("\\Y", sig_y); } -static void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell) +{ + RTLIL::SigSpec sig_a = cell->getPort("\\A"); + RTLIL::SigSpec sig_b = cell->getPort("\\B"); + RTLIL::SigSpec sig_y = cell->getPort("\\Y"); + bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool(); + bool is_ne = cell->type == "$ne" || cell->type == "$nex"; + + RTLIL::SigSpec xor_out = module->addWire(NEW_ID, std::max(GetSize(sig_a), GetSize(sig_b))); + RTLIL::Cell *xor_cell = module->addXor(NEW_ID, sig_a, sig_b, xor_out, is_signed); + + RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID); + RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID, xor_out, reduce_out); + + if (!is_ne) + module->addNotGate(NEW_ID, reduce_out, sig_y); + + simplemap_bitop(module, xor_cell); + module->remove(xor_cell); + + simplemap_reduce(module, reduce_cell); + module->remove(reduce_cell); +} + +void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell) { RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_b = cell->getPort("\\B"); @@ -247,7 +270,7 @@ static void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell) } } -static void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell) { int offset = cell->parameters.at("\\OFFSET").as_int(); RTLIL::SigSpec sig_a = cell->getPort("\\A"); @@ -255,7 +278,7 @@ static void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell) module->connect(RTLIL::SigSig(sig_y, sig_a.extract(offset, sig_y.size()))); } -static void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell) { RTLIL::SigSpec sig_ab = cell->getPort("\\A"); sig_ab.append(cell->getPort("\\B")); @@ -263,7 +286,7 @@ static void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell) module->connect(RTLIL::SigSig(sig_y, sig_ab)); } -static void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell) { int width = cell->parameters.at("\\WIDTH").as_int(); char set_pol = cell->parameters.at("\\SET_POLARITY").as_bool() ? 'P' : 'N'; @@ -283,7 +306,7 @@ static void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell) } } -static void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell) { int width = cell->parameters.at("\\WIDTH").as_int(); char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N'; @@ -302,7 +325,7 @@ static void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell) } } -static void simplemap_dffe(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_dffe(RTLIL::Module *module, RTLIL::Cell *cell) { int width = cell->parameters.at("\\WIDTH").as_int(); char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N'; @@ -324,7 +347,7 @@ static void simplemap_dffe(RTLIL::Module *module, RTLIL::Cell *cell) } } -static void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell) { int width = cell->parameters.at("\\WIDTH").as_int(); char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N'; @@ -349,7 +372,7 @@ static void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell) } } -static void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell) { int width = cell->parameters.at("\\WIDTH").as_int(); char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N'; @@ -376,7 +399,7 @@ static void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell) } } -static void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell) +void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell) { int width = cell->parameters.at("\\WIDTH").as_int(); char en_pol = cell->parameters.at("\\EN_POLARITY").as_bool() ? 'P' : 'N'; @@ -395,11 +418,6 @@ static void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell) } } -PRIVATE_NAMESPACE_END -YOSYS_NAMESPACE_BEGIN - -extern void simplemap_get_mappers(std::map &mappers); - void simplemap_get_mappers(std::map &mappers) { mappers["$not"] = simplemap_not; @@ -416,6 +434,10 @@ void simplemap_get_mappers(std::map mappers; + static bool initialized_mappers = false; + + if (!initialized_mappers) { + simplemap_get_mappers(mappers); + initialized_mappers = true; + } + + mappers.at(cell->type)(module, cell); +} + YOSYS_NAMESPACE_END PRIVATE_NAMESPACE_BEGIN diff --git a/passes/techmap/simplemap.h b/passes/techmap/simplemap.h new file mode 100644 index 000000000..dc2a395d3 --- /dev/null +++ b/passes/techmap/simplemap.h @@ -0,0 +1,48 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef SIMPLEMAP_H +#define SIMPLEMAP_H + +#include "kernel/yosys.h" + +YOSYS_NAMESPACE_BEGIN + +extern void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap_dffe(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell); +extern void simplemap(RTLIL::Module *module, RTLIL::Cell *cell); + +extern void simplemap_get_mappers(std::map &mappers); + +YOSYS_NAMESPACE_END + +#endif diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index e109c5b58..04d345d31 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -26,13 +26,11 @@ #include #include +#include "simplemap.h" #include "passes/techmap/techmap.inc" YOSYS_NAMESPACE_BEGIN -// see simplemap.cc -extern void simplemap_get_mappers(std::map &mappers); - // see maccmap.cc extern void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap = false); diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 7b5528560..e0ecf0c48 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -53,6 +53,11 @@ endmodule module _90_simplemap_logic_ops; endmodule +(* techmap_simplemap *) +(* techmap_celltype = "$eq $eqx $ne $nex" *) +module _90_simplemap_compare_ops; +endmodule + (* techmap_simplemap *) (* techmap_celltype = "$pos $slice $concat $mux" *) module _90_simplemap_various; @@ -406,55 +411,6 @@ module _90_pow (A, B, Y); endmodule -// -------------------------------------------------------- -// Equal and Not-Equal -// -------------------------------------------------------- - -(* techmap_celltype = "$eq $eqx" *) -module _90_eq_eqx (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire carry, carry_sign; - wire [WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - - assign Y = ~|(A_buf ^ B_buf); -endmodule - -(* techmap_celltype = "$ne $nex" *) -module _90_ne_nex (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire carry, carry_sign; - wire [WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - - assign Y = |(A_buf ^ B_buf); -endmodule - - // -------------------------------------------------------- // Parallel Multiplexers // -------------------------------------------------------- From afcacd643733521eeb08b3f139386556015bf2af Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 24 Dec 2014 10:49:54 +0100 Subject: [PATCH 166/492] Added support for gate-level cells in dff2dffe --- passes/techmap/dff2dffe.cc | 47 ++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/passes/techmap/dff2dffe.cc b/passes/techmap/dff2dffe.cc index 74f31f140..eda8bd9ac 100644 --- a/passes/techmap/dff2dffe.cc +++ b/passes/techmap/dff2dffe.cc @@ -20,6 +20,7 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/celltypes.h" +#include "passes/techmap/simplemap.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -47,12 +48,12 @@ struct Dff2dffeWorker } for (auto cell : module->cells()) { - if (cell->type == "$mux" || cell->type == "$pmux") { + if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$_MUX_") { RTLIL::SigSpec sig_y = sigmap(cell->getPort("\\Y")); for (int i = 0; i < GetSize(sig_y); i++) bit2mux[sig_y[i]] = cell_int_t(cell, i); } - if (cell->type == "$dff") + if (cell->type == "$dff" || cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_") dff_cells.push_back(cell); for (auto conn : cell->connections()) { if (ct.cell_output(cell->type, conn.first)) @@ -133,22 +134,44 @@ struct Dff2dffeWorker // TBD } - RTLIL::SigSpec make_patterns_logic(patterns_t patterns) + RTLIL::SigSpec make_patterns_logic(patterns_t patterns, bool make_gates) { RTLIL::SigSpec or_input; - for (auto pat : patterns) { + + for (auto pat : patterns) + { RTLIL::SigSpec s1, s2; for (auto it : pat) { s1.append(it.first); s2.append(it.second); } - or_input.append(module->Ne(NEW_ID, s1, s2)); + + RTLIL::SigSpec y = module->addWire(NEW_ID); + RTLIL::Cell *c = module->addNe(NEW_ID, s1, s2, y); + + if (make_gates) { + simplemap(module, c); + module->remove(c); + } + + or_input.append(y); } + if (GetSize(or_input) == 0) return RTLIL::S1; + if (GetSize(or_input) == 1) return or_input; - return module->ReduceOr(NEW_ID, or_input); + + RTLIL::SigSpec y = module->addWire(NEW_ID); + RTLIL::Cell *c = module->addReduceOr(NEW_ID, or_input, y); + + if (make_gates) { + simplemap(module, c); + module->remove(c); + } + + return y; } void handle_dff_cell(RTLIL::Cell *dff_cell) @@ -174,9 +197,15 @@ struct Dff2dffeWorker new_sig_d.append(sig_d[i]); new_sig_q.append(sig_q[i]); } - RTLIL::Cell *new_cell = module->addDffe(NEW_ID, dff_cell->getPort("\\CLK"), make_patterns_logic(it.first), - new_sig_d, new_sig_q, dff_cell->getParam("\\CLK_POLARITY").as_bool(), true); - log(" created $dffe cell %s for %s -> %s.\n", log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q)); + if (dff_cell->type == "$dff") { + RTLIL::Cell *new_cell = module->addDffe(NEW_ID, dff_cell->getPort("\\CLK"), make_patterns_logic(it.first, false), + new_sig_d, new_sig_q, dff_cell->getParam("\\CLK_POLARITY").as_bool(), true); + log(" created $dffe cell %s for %s -> %s.\n", log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q)); + } else { + RTLIL::Cell *new_cell = module->addDffeGate(NEW_ID, dff_cell->getPort("\\C"), make_patterns_logic(it.first, true), + new_sig_d, new_sig_q, dff_cell->type == "$_DFF_P_", true); + log(" created %s cell %s for %s -> %s.\n", log_id(new_cell->type), log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q)); + } } if (remaining_indices.empty()) { From 8c1a72c2a43ad9d681deaf31af579ca6ea2266b5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 24 Dec 2014 11:09:01 +0100 Subject: [PATCH 167/492] Added "dff2dffe -unmap" --- passes/techmap/dff2dffe.cc | 48 +++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/passes/techmap/dff2dffe.cc b/passes/techmap/dff2dffe.cc index eda8bd9ac..03abde6f9 100644 --- a/passes/techmap/dff2dffe.cc +++ b/passes/techmap/dff2dffe.cc @@ -241,25 +241,61 @@ struct Dff2dffePass : public Pass { log(" dff2dffe [selection]\n"); log("\n"); log("This pass transforms $dff cells driven by a tree of multiplexers with one or\n"); - log("more feedback paths to $dffe cells.\n"); + log("more feedback paths to $dffe cells. It also works on gate-level cells such as\n"); + log("$_DFF_P_, $_DFF_N_ and $_MUX_.\n"); + log("\n"); + log(" -unmap\n"); + log(" operate in the opposite direction: replace $dffe cells with combinations\n"); + log(" of $dff and $mux cells\n"); log("\n"); } virtual void execute(std::vector args, RTLIL::Design *design) { log_header("Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n"); + bool unmap_mode = false; + size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - // if (args[argidx] == "-foobar") { - // foobar_mode = true; - // continue; - // } + if (args[argidx] == "-unmap") { + unmap_mode = true; + continue; + } break; } extra_args(args, argidx, design); for (auto mod : design->selected_modules()) - if (!mod->has_processes_warn()) { + if (!mod->has_processes_warn()) + { + if (unmap_mode) { + for (auto cell : mod->selected_cells()) { + if (cell->type == "$dffe") { + RTLIL::SigSpec tmp = mod->addWire(NEW_ID, GetSize(cell->getPort("\\D"))); + mod->addDff(NEW_ID, cell->getPort("\\CLK"), tmp, cell->getPort("\\Q"), cell->getParam("\\CLK_POLARITY").as_bool()); + if (cell->getParam("\\EN_POLARITY").as_bool()) + mod->addMux(NEW_ID, cell->getPort("\\Q"), cell->getPort("\\D"), cell->getPort("\\EN"), tmp); + else + mod->addMux(NEW_ID, cell->getPort("\\D"), cell->getPort("\\Q"), cell->getPort("\\EN"), tmp); + mod->remove(cell); + continue; + } + if (cell->type.substr(0, 7) == "$_DFFE_") { + bool clk_pol = cell->type.substr(7, 1) == "P"; + bool en_pol = cell->type.substr(8, 1) == "P"; + RTLIL::SigSpec tmp = mod->addWire(NEW_ID); + mod->addDff(NEW_ID, cell->getPort("\\C"), tmp, cell->getPort("\\Q"), clk_pol); + if (en_pol) + mod->addMux(NEW_ID, cell->getPort("\\Q"), cell->getPort("\\D"), cell->getPort("\\E"), tmp); + else + mod->addMux(NEW_ID, cell->getPort("\\D"), cell->getPort("\\Q"), cell->getPort("\\E"), tmp); + mod->remove(cell); + continue; + } + } + continue; + } + Dff2dffeWorker worker(mod); worker.run(); } From 032ce573a3358d1eb5cd2d2f3ec724cc18b3626b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 24 Dec 2014 11:39:15 +0100 Subject: [PATCH 168/492] Added "dff2dffe -direct" for direct gate mapping --- passes/techmap/dff2dffe.cc | 42 +++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/passes/techmap/dff2dffe.cc b/passes/techmap/dff2dffe.cc index 03abde6f9..339007156 100644 --- a/passes/techmap/dff2dffe.cc +++ b/passes/techmap/dff2dffe.cc @@ -31,6 +31,8 @@ struct Dff2dffeWorker SigMap sigmap; CellTypes ct; + RTLIL::IdString direct_to; + typedef std::pair cell_int_t; std::map bit2mux; std::vector dff_cells; @@ -39,7 +41,9 @@ struct Dff2dffeWorker typedef std::map pattern_t; typedef std::set patterns_t; - Dff2dffeWorker(RTLIL::Module *module) : module(module), sigmap(module), ct(module->design) + + Dff2dffeWorker(RTLIL::Module *module, RTLIL::IdString direct_from, RTLIL::IdString direct_to) : + module(module), sigmap(module), ct(module->design), direct_to(direct_to) { for (auto wire : module->wires()) { if (wire->port_output) @@ -53,8 +57,13 @@ struct Dff2dffeWorker for (int i = 0; i < GetSize(sig_y); i++) bit2mux[sig_y[i]] = cell_int_t(cell, i); } - if (cell->type == "$dff" || cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_") - dff_cells.push_back(cell); + if (direct_to.empty()) { + if (cell->type == "$dff" || cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_") + dff_cells.push_back(cell); + } else { + if (cell->type == direct_from) + dff_cells.push_back(cell); + } for (auto conn : cell->connections()) { if (ct.cell_output(cell->type, conn.first)) continue; @@ -197,6 +206,11 @@ struct Dff2dffeWorker new_sig_d.append(sig_d[i]); new_sig_q.append(sig_q[i]); } + if (!direct_to.empty()) { + log(" converting %s cell %s to %s for %s -> %s.\n", log_id(dff_cell->type), log_id(dff_cell), log_id(direct_to), log_signal(new_sig_d), log_signal(new_sig_q)); + dff_cell->setPort("\\E", make_patterns_logic(it.first, true)); + dff_cell->type = direct_to; + } else if (dff_cell->type == "$dff") { RTLIL::Cell *new_cell = module->addDffe(NEW_ID, dff_cell->getPort("\\CLK"), make_patterns_logic(it.first, false), new_sig_d, new_sig_q, dff_cell->getParam("\\CLK_POLARITY").as_bool(), true); @@ -208,6 +222,9 @@ struct Dff2dffeWorker } } + if (!direct_to.empty()) + return; + if (remaining_indices.empty()) { log(" removing now obsolete cell %s.\n", log_id(dff_cell)); module->remove(dff_cell); @@ -246,7 +263,16 @@ struct Dff2dffePass : public Pass { log("\n"); log(" -unmap\n"); log(" operate in the opposite direction: replace $dffe cells with combinations\n"); - log(" of $dff and $mux cells\n"); + log(" of $dff and $mux cells. the options below are ignore in unmap mode.\n"); + log("\n"); + log(" -direct \n"); + log(" map directly to external gate type. can\n"); + log(" be any internal gate-level FF cell (except $_DFFE_??_). the\n"); + log(" is the cell type name for a cell with an\n"); + log(" identical interface to the , except it\n"); + log(" also has an high-active enable port 'E'.\n"); + log(" Usually is an intemediate cell type\n"); + log(" that is then translated to the final type using 'techmap'.\n"); log("\n"); } virtual void execute(std::vector args, RTLIL::Design *design) @@ -254,6 +280,7 @@ struct Dff2dffePass : public Pass { log_header("Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n"); bool unmap_mode = false; + RTLIL::IdString direct_from, direct_to; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -261,6 +288,11 @@ struct Dff2dffePass : public Pass { unmap_mode = true; continue; } + if (args[argidx] == "-direct" && argidx + 2 < args.size()) { + direct_from = RTLIL::escape_id(args[++argidx]); + direct_to = RTLIL::escape_id(args[++argidx]); + continue; + } break; } extra_args(args, argidx, design); @@ -296,7 +328,7 @@ struct Dff2dffePass : public Pass { continue; } - Dff2dffeWorker worker(mod); + Dff2dffeWorker worker(mod, direct_from, direct_to); worker.run(); } } From 35f5aa300f4cdfc19293f0e5722159d7f0a212de Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 24 Dec 2014 12:19:20 +0100 Subject: [PATCH 169/492] Added "dfflibmap -prepare" --- passes/techmap/dfflibmap.cc | 81 ++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index a02eafb96..58f0c2542 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -103,7 +103,7 @@ static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name, return false; } -static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval) +static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, bool prepare_mode) { LibertyAst *best_cell = NULL; std::map best_cell_ports; @@ -193,13 +193,22 @@ static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool } if (best_cell != NULL) { - log(" cell %s (pins=%d, area=%.2f) is a direct match for cell type %s.\n", best_cell->args[0].c_str(), best_cell_pins, best_cell_area, cell_type.substr(1).c_str()); - cell_mappings[cell_type].cell_name = best_cell->args[0]; - cell_mappings[cell_type].ports = best_cell_ports; + log(" cell %s (pins=%d, area=%.2f) is a direct match for cell type %s.\n", best_cell->args[0].c_str(), best_cell_pins, best_cell_area, cell_type.c_str()); + if (prepare_mode) { + cell_mappings[cell_type].cell_name = cell_type; + cell_mappings[cell_type].ports["C"] = 'C'; + if (has_reset) + cell_mappings[cell_type].ports["R"] = 'R'; + cell_mappings[cell_type].ports["D"] = 'D'; + cell_mappings[cell_type].ports["Q"] = 'Q'; + } else { + cell_mappings[cell_type].cell_name = best_cell->args[0]; + cell_mappings[cell_type].ports = best_cell_ports; + } } } -static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bool setpol, bool clrpol) +static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bool setpol, bool clrpol, bool prepare_mode) { LibertyAst *best_cell = NULL; std::map best_cell_ports; @@ -285,9 +294,18 @@ static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bo } if (best_cell != NULL) { - log(" cell %s (pins=%d, area=%.2f) is a direct match for cell type %s.\n", best_cell->args[0].c_str(), best_cell_pins, best_cell_area, cell_type.substr(1).c_str()); - cell_mappings[cell_type].cell_name = best_cell->args[0]; - cell_mappings[cell_type].ports = best_cell_ports; + log(" cell %s (pins=%d, area=%.2f) is a direct match for cell type %s.\n", best_cell->args[0].c_str(), best_cell_pins, best_cell_area, cell_type.c_str()); + if (prepare_mode) { + cell_mappings[cell_type].cell_name = cell_type; + cell_mappings[cell_type].ports["C"] = 'C'; + cell_mappings[cell_type].ports["S"] = 'S'; + cell_mappings[cell_type].ports["R"] = 'R'; + cell_mappings[cell_type].ports["D"] = 'D'; + cell_mappings[cell_type].ports["Q"] = 'Q'; + } else { + cell_mappings[cell_type].cell_name = best_cell->args[0]; + cell_mappings[cell_type].ports = best_cell_ports; + } } } @@ -384,7 +402,7 @@ static void map_sr_to_arst(const char *from, const char *to) } } -static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module) +static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare_mode) { log("Mapping DFF cells in module `%s':\n", module->name.c_str()); @@ -403,7 +421,7 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module) module->remove(cell); cell_mapping &cm = cell_mappings[cell_type]; - RTLIL::Cell *new_cell = module->addCell(cell_name, "\\" + cm.cell_name); + RTLIL::Cell *new_cell = module->addCell(cell_name, prepare_mode ? cm.cell_name : "\\" + cm.cell_name); for (auto &port : cm.ports) { RTLIL::SigSpec sig; @@ -453,6 +471,7 @@ struct DfflibmapPass : public Pass { log_header("Executing DFFLIBMAP pass (mapping DFF cells to sequential cells from liberty file).\n"); std::string liberty_file; + bool prepare_mode = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -462,6 +481,10 @@ struct DfflibmapPass : public Pass { liberty_file = args[++argidx]; continue; } + if (arg == "-prepare") { + prepare_mode = true; + continue; + } break; } extra_args(args, argidx, design); @@ -476,26 +499,26 @@ struct DfflibmapPass : public Pass { LibertyParser libparser(f); f.close(); - find_cell(libparser.ast, "$_DFF_N_", false, false, false, false); - find_cell(libparser.ast, "$_DFF_P_", true, false, false, false); + find_cell(libparser.ast, "$_DFF_N_", false, false, false, false, prepare_mode); + find_cell(libparser.ast, "$_DFF_P_", true, false, false, false, prepare_mode); - find_cell(libparser.ast, "$_DFF_NN0_", false, true, false, false); - find_cell(libparser.ast, "$_DFF_NN1_", false, true, false, true); - find_cell(libparser.ast, "$_DFF_NP0_", false, true, true, false); - find_cell(libparser.ast, "$_DFF_NP1_", false, true, true, true); - find_cell(libparser.ast, "$_DFF_PN0_", true, true, false, false); - find_cell(libparser.ast, "$_DFF_PN1_", true, true, false, true); - find_cell(libparser.ast, "$_DFF_PP0_", true, true, true, false); - find_cell(libparser.ast, "$_DFF_PP1_", true, true, true, true); + find_cell(libparser.ast, "$_DFF_NN0_", false, true, false, false, prepare_mode); + find_cell(libparser.ast, "$_DFF_NN1_", false, true, false, true, prepare_mode); + find_cell(libparser.ast, "$_DFF_NP0_", false, true, true, false, prepare_mode); + find_cell(libparser.ast, "$_DFF_NP1_", false, true, true, true, prepare_mode); + find_cell(libparser.ast, "$_DFF_PN0_", true, true, false, false, prepare_mode); + find_cell(libparser.ast, "$_DFF_PN1_", true, true, false, true, prepare_mode); + find_cell(libparser.ast, "$_DFF_PP0_", true, true, true, false, prepare_mode); + find_cell(libparser.ast, "$_DFF_PP1_", true, true, true, true, prepare_mode); - find_cell_sr(libparser.ast, "$_DFFSR_NNN_", false, false, false); - find_cell_sr(libparser.ast, "$_DFFSR_NNP_", false, false, true); - find_cell_sr(libparser.ast, "$_DFFSR_NPN_", false, true, false); - find_cell_sr(libparser.ast, "$_DFFSR_NPP_", false, true, true); - find_cell_sr(libparser.ast, "$_DFFSR_PNN_", true, false, false); - find_cell_sr(libparser.ast, "$_DFFSR_PNP_", true, false, true); - find_cell_sr(libparser.ast, "$_DFFSR_PPN_", true, true, false); - find_cell_sr(libparser.ast, "$_DFFSR_PPP_", true, true, true); + find_cell_sr(libparser.ast, "$_DFFSR_NNN_", false, false, false, prepare_mode); + find_cell_sr(libparser.ast, "$_DFFSR_NNP_", false, false, true, prepare_mode); + find_cell_sr(libparser.ast, "$_DFFSR_NPN_", false, true, false, prepare_mode); + find_cell_sr(libparser.ast, "$_DFFSR_NPP_", false, true, true, prepare_mode); + find_cell_sr(libparser.ast, "$_DFFSR_PNN_", true, false, false, prepare_mode); + find_cell_sr(libparser.ast, "$_DFFSR_PNP_", true, false, true, prepare_mode); + find_cell_sr(libparser.ast, "$_DFFSR_PPN_", true, true, false, prepare_mode); + find_cell_sr(libparser.ast, "$_DFFSR_PPP_", true, true, true, prepare_mode); // try to implement as many cells as possible just by inverting // the SET and RESET pins. If necessary, implement cell types @@ -533,7 +556,7 @@ struct DfflibmapPass : public Pass { for (auto &it : design->modules_) if (design->selected(it.second) && !it.second->get_bool_attribute("\\blackbox")) - dfflibmap(design, it.second); + dfflibmap(design, it.second, prepare_mode); cell_mappings.clear(); } From aad195b88ce55d46fe741b217efc66b3aa259535 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 24 Dec 2014 12:56:05 +0100 Subject: [PATCH 170/492] Added "dfflibmap -prepare" help --- passes/techmap/dfflibmap.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index 58f0c2542..cc6f97c7e 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -457,7 +457,7 @@ struct DfflibmapPass : public Pass { virtual void help() { log("\n"); - log(" dfflibmap -liberty [selection]\n"); + log(" dfflibmap [-prepare] -liberty [selection]\n"); log("\n"); log("Map internal flip-flop cells to the flip-flop cells in the technology\n"); log("library specified in the given liberty file.\n"); @@ -465,6 +465,10 @@ struct DfflibmapPass : public Pass { log("This pass may add inverters as needed. Therefore it is recommended to\n"); log("first run this pass and then map the logic paths to the target technology.\n"); log("\n"); + log("When called with -prepare, this command will convert the internal FF cells\n"); + log("to the internal cell types that best match the cells found in the given\n"); + log("liberty file.\n"); + log("\n"); } virtual void execute(std::vector args, RTLIL::Design *design) { From e548483c9105a0fef0a4b5c64640611b304ecb05 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 24 Dec 2014 16:17:57 +0100 Subject: [PATCH 171/492] Added write_smt2 (only gate level logic supported so far) --- backends/smt2/Makefile.inc | 3 + backends/smt2/smt2.cc | 350 +++++++++++++++++++++++++++++++++++++ 2 files changed, 353 insertions(+) create mode 100644 backends/smt2/Makefile.inc create mode 100644 backends/smt2/smt2.cc diff --git a/backends/smt2/Makefile.inc b/backends/smt2/Makefile.inc new file mode 100644 index 000000000..4e0a393a8 --- /dev/null +++ b/backends/smt2/Makefile.inc @@ -0,0 +1,3 @@ + +OBJS += backends/smt2/smt2.o + diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc new file mode 100644 index 000000000..d5cf856b4 --- /dev/null +++ b/backends/smt2/smt2.cc @@ -0,0 +1,350 @@ +/* + * 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/rtlil.h" +#include "kernel/register.h" +#include "kernel/sigtools.h" +#include "kernel/celltypes.h" +#include "kernel/log.h" +#include + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct Smt2Worker +{ + CellTypes ct; + SigMap sigmap; + RTLIL::Module *module; + + std::vector decls, clauses, trans; + std::map bool_cache; + std::map> cells_by_type; + + Smt2Worker(RTLIL::Module *module) : ct(module->design), sigmap(module), module(module) + { + decls.push_back(stringf("(declare-sort |%s_s| 0)\n", log_id(module))); + } + + std::string get_bool(RTLIL::SigBit bit, const char *state_name = "state") + { + sigmap.apply(bit); + + if (bit.wire == nullptr) + return bit.data == RTLIL::State::S1 ? "true" : "false"; + + if (!bool_cache.count(bit)) { + std::string name = stringf("|%s_n %s %d|", log_id(module), log_id(bit.wire), bit.offset); + for (auto &c : name) + if (c == '\\') c = '/'; + decls.push_back(stringf("(declare-fun %s (|%s_s|) Bool)\n", name.c_str(), log_id(module))); + bool_cache[bit] = name; + } + + return stringf("(%s %s)", bool_cache.at(bit).c_str(), state_name); + } + + void make_wire(RTLIL::Wire *wire) + { + for (int i = 0; i < GetSize(wire); i++) + get_bool(RTLIL::SigBit(wire, i)); + } + + void run_gates() + { + // basic gate-level logic cell types + + for (auto cell : cells_by_type["$_BUF_"]) + clauses.push_back(stringf(" (= %s %s)\n", + get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); + cells_by_type.erase("$_BUF_"); + + for (auto cell : cells_by_type["$_NOT_"]) + clauses.push_back(stringf(" (distinct %s %s)\n", + get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); + cells_by_type.erase("$_NOT_"); + + for (auto cell : cells_by_type["$_AND_"]) + clauses.push_back(stringf(" (= (and %s %s) %s)\n", + get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); + cells_by_type.erase("$_AND_"); + + for (auto cell : cells_by_type["$_OR_"]) + clauses.push_back(stringf(" (= (or %s %s) %s)\n", + get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); + cells_by_type.erase("$_OR_"); + + for (auto cell : cells_by_type["$_XOR_"]) + clauses.push_back(stringf(" (= (xor %s %s) %s)\n", + get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); + cells_by_type.erase("$_XOR_"); + + for (auto cell : cells_by_type["$_MUX_"]) + clauses.push_back(stringf(" (= (ite %s %s %s) %s)\n", + get_bool(cell->getPort("\\S").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); + cells_by_type.erase("$_MUX_"); + + + // inverted gate-level logic cell types + + for (auto cell : cells_by_type["$_NAND_"]) + clauses.push_back(stringf(" (distinct (and %s %s) %s)\n", + get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); + cells_by_type.erase("$_NAND_"); + + for (auto cell : cells_by_type["$_NOR_"]) + clauses.push_back(stringf(" (distinct (or %s %s) %s)\n", + get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); + cells_by_type.erase("$_NOR_"); + + for (auto cell : cells_by_type["$_XNOR_"]) + clauses.push_back(stringf(" (distinct (xor %s %s) %s)\n", + get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); + cells_by_type.erase("$_XNOR_"); + + + // advanced cmos-style logic cell types + + for (auto cell : cells_by_type["$_AOI3_"]) + clauses.push_back(stringf(" (distinct (or (and %s %s) %s) %s)\n", + get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\C").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); + cells_by_type.erase("$_AOI3_"); + + for (auto cell : cells_by_type["$_AOI4_"]) + clauses.push_back(stringf(" (distinct (or (and %s %s) (and %s %s)) %s)\n", + get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\C").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\D").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); + cells_by_type.erase("$_AOI4_"); + + for (auto cell : cells_by_type["$_OAI3_"]) + clauses.push_back(stringf(" (distinct (or (and %s %s) %s) %s)\n", + get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\C").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); + cells_by_type.erase("$_OAI3_"); + + for (auto cell : cells_by_type["$_OAI4_"]) + clauses.push_back(stringf(" (distinct (or (and %s %s) (and %s %s)) %s)\n", + get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\C").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\D").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); + cells_by_type.erase("$_OAI4_"); + + + // simple DFF cells (ignoring clock domains) + + for (auto cell : cells_by_type["$_DFF_P_"]) + trans.push_back(stringf(" (= %s %s)\n", + get_bool(cell->getPort("\\D").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Q").to_single_sigbit(), "next_state").c_str())); + cells_by_type.erase("$_DFF_P_"); + + for (auto cell : cells_by_type["$_DFF_N_"]) + trans.push_back(stringf(" (= %s %s)\n", + get_bool(cell->getPort("\\D").to_single_sigbit()).c_str(), + get_bool(cell->getPort("\\Q").to_single_sigbit(), "next_state").c_str())); + cells_by_type.erase("$_DFF_N_"); + } + + void run() + { + for (auto port : module->ports) + make_wire(module->wire(port)); + + for (auto cell : module->cells()) + cells_by_type[cell->type].push_back(cell); + + run_gates(); + + for (auto &it : cells_by_type) + log_error("Found %d cells of unsupported type %s in module %s.\n", GetSize(it.second), log_id(it.first), log_id(module)); + } + + void write(std::ostream &f) + { + for (auto it : decls) + f << it; + f << stringf("(define-fun |%s_c| ((state |%s_s|)) Bool (and\n", log_id(module), log_id(module)); + for (auto it : clauses) + f << it; + f << "true true))\n"; + f << stringf("(define-fun |%s_t| ((state |%s_s|)(next_state |%s_s|)) Bool (and\n", log_id(module), log_id(module), log_id(module)); + for (auto it : trans) + f << it; + f << "true true))\n"; + } +}; + +struct Smt2Backend : public Backend { + Smt2Backend() : Backend("smt2", "write design to SMT-LIBv2 file") { } + virtual void help() + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" write_smt2 [options] [filename]\n"); + log("\n"); + log("Write a SMT-LIBv2 description of the current design. For a module with name\n"); + log("'' this will declare the sort '_s' and the two functions '_c'\n"); + log("(of arity 1) and '_t' (of arity 2).\n"); + log("\n"); + log("The sort represents the state of the module. Additional '_n' functions are\n"); + log("declared that can be used to access the values of all signals in the module.\n"); + log("\n"); + log("The '_c' function evaluates to 'true' when the given state is consistent\n"); + log("with the description of the models.\n"); + log("\n"); + log("The '_t' function evaluates to 'true' when the given pair of states is\n"); + log("describes a valid state transition, provided that '_c' is true for both\n"); + log("states.\n"); + log("\n"); + log(" -tpl \n"); + log(" use the given template file. the line containing only the token '%%%%'\n"); + log(" is replaced with the regular output of this command.\n"); + log("\n"); + log("---------------------------------------------------------------------------\n"); + log("\n"); + log("Example:\n"); + log("\n"); + log("Consider the following module (test.v). We want to prove that the output can\n"); + log("never transition from a non-zero value to a zero value.\n"); + log("\n"); + log(" module test(input clk, output reg [3:0] y);\n"); + log(" always @(posedge clk)\n"); + log(" y <= (y << 1) | ^y;\n"); + log(" endmodule\n"); + log("\n"); + log("For this proof we create the following template (test.tpl).\n"); + log("\n"); + log(" ; we only need QF_UF for this poof\n"); + log(" (set-logic QF_UF)\n"); + log("\n"); + log(" ; insert the auto-generated code here\n"); + log(" %%%%\n"); + log("\n"); + log(" ; declare two state variables s1 and s2\n"); + log(" (declare-fun s1 () test_s)\n"); + log(" (declare-fun s2 () test_s)\n"); + log("\n"); + log(" ; both states are valid and s2 follows s1\n"); + log(" (assert (test_c s1))\n"); + log(" (assert (test_c s2))\n"); + log(" (assert (test_t s1 s2))\n"); + log("\n"); + log(" ; we are looking for a solution with y non-zero in s1\n"); + log(" (assert (or (|test_n y 0| s1) (|test_n y 1| s1)\n"); + log(" (|test_n y 2| s1) (|test_n y 3| s1)))\n"); + log("\n"); + log(" ; we are looking for a solution with y zero in s2\n"); + log(" (assert (not (or (|test_n y 0| s2) (|test_n y 1| s2)\n"); + log(" (|test_n y 2| s2) (|test_n y 3| s2))))\n"); + log("\n"); + log(" ; is there such a solution?\n"); + log(" (check-sat)\n"); + log("\n"); + log("The following yosys script will create a 'test.smt2' file for our proof:\n"); + log("\n"); + log(" read_verilog test.v\n"); + log(" hierarchy; proc; techmap; opt -fast\n"); + log(" write_smt2 -template test.tpl test.smt2\n"); + log("\n"); + log("Running 'cvc4 test.smt2' will print 'unsat' because y can never transition\n"); + 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) + { + std::ifstream template_f; + log_header("Executing SMT2 backend.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-template" && argidx+1 < args.size()) { + template_f.open(args[++argidx]); + if (template_f.fail()) + log_error("Can't open template file `%s'.\n", args[argidx].c_str()); + continue; + } + break; + } + extra_args(f, filename, args, argidx); + + if (template_f.is_open()) { + std::string line; + while (std::getline(template_f, line)) { + int indent = 0; + while (indent < GetSize(line) && (line[indent] == ' ' || line[indent] == '\t')) + indent++; + if (line.substr(indent, 2) == "%%") + break; + *f << line << std::endl; + } + } + + *f << stringf("; SMT-LIBv2 description generated by %s\n", yosys_version_str); + + for (auto module : design->modules()) + { + if (module->get_bool_attribute("\\blackbox") || module->has_memories_warn() || module->has_processes_warn()) + continue; + + log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module)); + + Smt2Worker worker(module); + worker.run(); + worker.write(*f); + } + + *f << stringf("; end of yosys output\n"); + + if (template_f.is_open()) { + std::string line; + while (std::getline(template_f, line)) + *f << line << std::endl; + } + } +} Smt2Backend; + +PRIVATE_NAMESPACE_END From b6a7e21d2ee773b2eedf55ded913b034e916fa27 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 24 Dec 2014 16:26:18 +0100 Subject: [PATCH 172/492] Fixed off-by-one bug in "hierarchy -check" for positional module args --- passes/hierarchy/hierarchy.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 028a0f0c2..e95947a92 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -206,9 +206,9 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check for (auto &conn : cell->connections()) if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') { int id = atoi(conn.first.c_str()+1); - if (id < 0 || id >= GetSize(mod->ports)) + if (id <= 0 || id > GetSize(mod->ports)) log_error("Module `%s' referenced in module `%s' in cell `%s' has only %d ports, requested port %d.\n", - log_id(cell->type), log_id(module), log_id(cell), GetSize(mod->ports), id + 1); + log_id(cell->type), log_id(module), log_id(cell), GetSize(mod->ports), id); } else if (mod->wire(conn.first) == nullptr || mod->wire(conn.first)->port_id == 0) log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a port named '%s'.\n", log_id(cell->type), log_id(module), log_id(cell), log_id(conn.first)); From 1c3d51375f787a80024da12d03150ff1be4939b5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 25 Dec 2014 13:30:20 +0100 Subject: [PATCH 173/492] Added "write_smt2 -bv" and other write_smt2 improvements --- backends/smt2/smt2.cc | 317 ++++++++++++++++++++---------------------- 1 file changed, 149 insertions(+), 168 deletions(-) diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index d5cf856b4..bad7b9b03 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -32,184 +32,155 @@ struct Smt2Worker CellTypes ct; SigMap sigmap; RTLIL::Module *module; + bool bvmode; + int idcounter; - std::vector decls, clauses, trans; - std::map bool_cache; - std::map> cells_by_type; + std::vector decls, trans; + std::map bit_driver; + std::set exported_cells; - Smt2Worker(RTLIL::Module *module) : ct(module->design), sigmap(module), module(module) + std::map> fcache; + std::map bvsizes; + + Smt2Worker(RTLIL::Module *module, bool bvmode) : ct(module->design), sigmap(module), module(module), bvmode(bvmode), idcounter(0) { decls.push_back(stringf("(declare-sort |%s_s| 0)\n", log_id(module))); + + for (auto cell : module->cells()) + for (auto &conn : cell->connections()) { + bool is_input = ct.cell_input(cell->type, conn.first); + bool is_output = ct.cell_output(cell->type, conn.first); + if (is_output && !is_input) + for (auto bit : sigmap(conn.second)) { + if (bit_driver.count(bit)) + log_error("Found multiple drivers for %s.\n", log_signal(bit)); + bit_driver[bit] = cell; + } + else if (is_output || !is_input) + log_error("Unsupported or unknown directionality on port %s of cell %s.%s (%s).\n", + log_id(conn.first), log_id(module), log_id(cell), log_id(cell->type)); + } + } + + void register_bool(RTLIL::SigBit bit, int id) + { + sigmap.apply(bit); + log_assert(fcache.count(bit) == 0); + fcache[bit] = std::pair(id, -1); } std::string get_bool(RTLIL::SigBit bit, const char *state_name = "state") { sigmap.apply(bit); - if (bit.wire == nullptr) - return bit.data == RTLIL::State::S1 ? "true" : "false"; + if (bit_driver.count(bit)) + export_cell(bit_driver.at(bit)); - if (!bool_cache.count(bit)) { - std::string name = stringf("|%s_n %s %d|", log_id(module), log_id(bit.wire), bit.offset); - for (auto &c : name) - if (c == '\\') c = '/'; - decls.push_back(stringf("(declare-fun %s (|%s_s|) Bool)\n", name.c_str(), log_id(module))); - bool_cache[bit] = name; + if (fcache.count(bit) == 0) { + decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) Bool) ; %s\n", + log_id(module), idcounter, log_id(module), log_signal(bit))); + register_bool(bit, idcounter++); } - return stringf("(%s %s)", bool_cache.at(bit).c_str(), state_name); + auto f = fcache.at(bit); + log_assert(f.second == -1); + return stringf("(|%s#%d| %s)", log_id(module), f.first, state_name); } - void make_wire(RTLIL::Wire *wire) + std::string get_bv(RTLIL::SigSpec sig, const char *state_name = "state") { - for (int i = 0; i < GetSize(wire); i++) - get_bool(RTLIL::SigBit(wire, i)); + std::vector subexpr; + + for (auto bit : sig) + subexpr.push_back(stringf("(ite %s #b1 #b0)", get_bool(bit, state_name).c_str())); + + if (GetSize(subexpr) > 1) { + std::string expr = "(concat"; + for (int i = GetSize(subexpr)-1; i >= 0; i--) + expr += " " + subexpr[i]; + return expr + ")"; + } else { + log_assert(GetSize(subexpr) == 1); + return subexpr[0]; + } } - void run_gates() + void export_gate(RTLIL::Cell *cell, std::string expr) { - // basic gate-level logic cell types + RTLIL::SigBit bit = sigmap(cell->getPort("\\Y")[0]); + std::string processed_expr; - for (auto cell : cells_by_type["$_BUF_"]) - clauses.push_back(stringf(" (= %s %s)\n", - get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); - cells_by_type.erase("$_BUF_"); + for (char ch : expr) { + if (ch == 'A') processed_expr += get_bool(cell->getPort("\\A")[0]); + else if (ch == 'B') processed_expr += get_bool(cell->getPort("\\B")[0]); + else if (ch == 'C') processed_expr += get_bool(cell->getPort("\\C")[0]); + else if (ch == 'D') processed_expr += get_bool(cell->getPort("\\D")[0]); + else if (ch == 'S') processed_expr += get_bool(cell->getPort("\\S")[0]); + else processed_expr += ch; + } - for (auto cell : cells_by_type["$_NOT_"]) - clauses.push_back(stringf(" (distinct %s %s)\n", - get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); - cells_by_type.erase("$_NOT_"); + decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n", + log_id(module), idcounter, log_id(module), processed_expr.c_str(), log_signal(bit))); + register_bool(bit, idcounter++); + return; + } - for (auto cell : cells_by_type["$_AND_"]) - clauses.push_back(stringf(" (= (and %s %s) %s)\n", - get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); - cells_by_type.erase("$_AND_"); + void export_cell(RTLIL::Cell *cell) + { + if (exported_cells.count(cell)) + return; + exported_cells.insert(cell); - for (auto cell : cells_by_type["$_OR_"]) - clauses.push_back(stringf(" (= (or %s %s) %s)\n", - get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); - cells_by_type.erase("$_OR_"); + if (cell->type == "$_DFF_P_" || cell->type == "$_DFF_N_") + { + std::string expr_d = get_bool(cell->getPort("\\D")[0]); + std::string expr_q = get_bool(cell->getPort("\\Q")[0], "next_state"); + trans.push_back(stringf(" (= %s %s)\n", expr_d.c_str(), expr_q.c_str())); + return; + } - for (auto cell : cells_by_type["$_XOR_"]) - clauses.push_back(stringf(" (= (xor %s %s) %s)\n", - get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); - cells_by_type.erase("$_XOR_"); + if (cell->type == "$_BUF_") return export_gate(cell, "A"); + if (cell->type == "$_NOT_") return export_gate(cell, "(not A)"); + if (cell->type == "$_AND_") return export_gate(cell, "(and A B)"); + if (cell->type == "$_NAND_") return export_gate(cell, "(not (and A B))"); + if (cell->type == "$_OR_") return export_gate(cell, "(or A B)"); + if (cell->type == "$_NOR_") return export_gate(cell, "(not (or A B))"); + if (cell->type == "$_XOR_") return export_gate(cell, "(xor A B)"); + if (cell->type == "$_XNOR_") return export_gate(cell, "(not (xor A B))"); + if (cell->type == "$_MUX_") return export_gate(cell, "(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)))"); + if (cell->type == "$_OAI4_") return export_gate(cell, "(not (and (or A B) (or C D)))"); - for (auto cell : cells_by_type["$_MUX_"]) - clauses.push_back(stringf(" (= (ite %s %s %s) %s)\n", - get_bool(cell->getPort("\\S").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); - cells_by_type.erase("$_MUX_"); - - - // inverted gate-level logic cell types - - for (auto cell : cells_by_type["$_NAND_"]) - clauses.push_back(stringf(" (distinct (and %s %s) %s)\n", - get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); - cells_by_type.erase("$_NAND_"); - - for (auto cell : cells_by_type["$_NOR_"]) - clauses.push_back(stringf(" (distinct (or %s %s) %s)\n", - get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); - cells_by_type.erase("$_NOR_"); - - for (auto cell : cells_by_type["$_XNOR_"]) - clauses.push_back(stringf(" (distinct (xor %s %s) %s)\n", - get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); - cells_by_type.erase("$_XNOR_"); - - - // advanced cmos-style logic cell types - - for (auto cell : cells_by_type["$_AOI3_"]) - clauses.push_back(stringf(" (distinct (or (and %s %s) %s) %s)\n", - get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\C").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); - cells_by_type.erase("$_AOI3_"); - - for (auto cell : cells_by_type["$_AOI4_"]) - clauses.push_back(stringf(" (distinct (or (and %s %s) (and %s %s)) %s)\n", - get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\C").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\D").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); - cells_by_type.erase("$_AOI4_"); - - for (auto cell : cells_by_type["$_OAI3_"]) - clauses.push_back(stringf(" (distinct (or (and %s %s) %s) %s)\n", - get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\C").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); - cells_by_type.erase("$_OAI3_"); - - for (auto cell : cells_by_type["$_OAI4_"]) - clauses.push_back(stringf(" (distinct (or (and %s %s) (and %s %s)) %s)\n", - get_bool(cell->getPort("\\A").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\B").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\C").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\D").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Y").to_single_sigbit()).c_str())); - cells_by_type.erase("$_OAI4_"); - - - // simple DFF cells (ignoring clock domains) - - for (auto cell : cells_by_type["$_DFF_P_"]) - trans.push_back(stringf(" (= %s %s)\n", - get_bool(cell->getPort("\\D").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Q").to_single_sigbit(), "next_state").c_str())); - cells_by_type.erase("$_DFF_P_"); - - for (auto cell : cells_by_type["$_DFF_N_"]) - trans.push_back(stringf(" (= %s %s)\n", - get_bool(cell->getPort("\\D").to_single_sigbit()).c_str(), - get_bool(cell->getPort("\\Q").to_single_sigbit(), "next_state").c_str())); - cells_by_type.erase("$_DFF_N_"); + log_error("Unsupported cell type %s for cell %s.%s.\n", + log_id(cell->type), log_id(module), log_id(cell)); } void run() { - for (auto port : module->ports) - make_wire(module->wire(port)); - - for (auto cell : module->cells()) - cells_by_type[cell->type].push_back(cell); - - run_gates(); - - for (auto &it : cells_by_type) - log_error("Found %d cells of unsupported type %s in module %s.\n", GetSize(it.second), log_id(it.first), log_id(module)); + for (auto wire : module->wires()) + if (wire->port_id || wire->get_bool_attribute("\\keep")) { + RTLIL::SigSpec sig = sigmap(wire); + if (bvmode && GetSize(sig) > 1) { + decls.push_back(stringf("(define-fun |%s_n %s| ((state |%s_s|)) (_ BitVec %d) %s)\n", + log_id(module), log_id(wire), log_id(module), GetSize(sig), get_bv(sig).c_str())); + } else { + for (int i = 0; i < GetSize(sig); i++) + if (GetSize(sig) > 1) + decls.push_back(stringf("(define-fun |%s_n %s %d| ((state |%s_s|)) Bool %s)\n", + log_id(module), log_id(wire), i, log_id(module), get_bool(sig[i]).c_str())); + else + decls.push_back(stringf("(define-fun |%s_n %s| ((state |%s_s|)) Bool %s)\n", + log_id(module), log_id(wire), log_id(module), get_bool(sig[i]).c_str())); + } + } } void write(std::ostream &f) { for (auto it : decls) f << it; - f << stringf("(define-fun |%s_c| ((state |%s_s|)) Bool (and\n", log_id(module), log_id(module)); - for (auto it : clauses) - f << it; - f << "true true))\n"; f << stringf("(define-fun |%s_t| ((state |%s_s|)(next_state |%s_s|)) Bool (and\n", log_id(module), log_id(module), log_id(module)); for (auto it : trans) f << it; @@ -225,24 +196,32 @@ struct Smt2Backend : public Backend { log("\n"); log(" write_smt2 [options] [filename]\n"); log("\n"); - log("Write a SMT-LIBv2 description of the current design. For a module with name\n"); - log("'' this will declare the sort '_s' and the two functions '_c'\n"); - log("(of arity 1) and '_t' (of arity 2).\n"); + log("Write a SMT-LIBv2 [1] description of the current design. For a module with name\n"); + log("'' this will declare the sort '_s' (state of the module) and the the\n"); + log("function '_t' (state transition function).\n"); log("\n"); - log("The sort represents the state of the module. Additional '_n' functions are\n"); - log("declared that can be used to access the values of all signals in the module.\n"); + log("The '_s' sort represents the a module state. Additional '_n' functions\n"); + log("are provided that can be used to access the values of all signals in the module.\n"); + log("Only ports, and signals with the 'keep' attribute set are made available via\n"); + log("such functions. Without the -bv option, multi-bit wires are exported as\n"); + log("separate functions of type Bool for the individual bits. With the -bv option\n"); + log("multi-bit wires are exported as single functions of type BitVec.\n"); log("\n"); - log("The '_c' function evaluates to 'true' when the given state is consistent\n"); - log("with the description of the models.\n"); + log("The '_t' function evaluates to 'true' when the given pair of states\n"); + log("describes a valid state transition.\n"); log("\n"); - log("The '_t' function evaluates to 'true' when the given pair of states is\n"); - log("describes a valid state transition, provided that '_c' is true for both\n"); - log("states.\n"); + log(" -bv\n"); + log(" enable support for BitVec (FixedSizeBitVectors theory). with this\n"); + log(" option set multi-bit wires are represented using the BitVec sort and\n"); + log(" support for coarse grain cells (incl. arithmetic) is enabled.\n"); log("\n"); log(" -tpl \n"); log(" use the given template file. the line containing only the token '%%%%'\n"); log(" is replaced with the regular output of this command.\n"); log("\n"); + log("[1] For more information on SMT-LIBv2 visit http://smt-lib.org/ or read David\n"); + log("R. Cok's tutorial: http://www.grammatech.com/resources/smt/SMTLIBTutorial.pdf\n"); + log("\n"); log("---------------------------------------------------------------------------\n"); log("\n"); log("Example:\n"); @@ -257,8 +236,8 @@ struct Smt2Backend : public Backend { log("\n"); log("For this proof we create the following template (test.tpl).\n"); log("\n"); - log(" ; we only need QF_UF for this poof\n"); - log(" (set-logic QF_UF)\n"); + log(" ; we need QF_UFBV for this poof\n"); + log(" (set-logic QF_UFBV)\n"); log("\n"); log(" ; insert the auto-generated code here\n"); log(" %%%%\n"); @@ -267,27 +246,23 @@ struct Smt2Backend : public Backend { log(" (declare-fun s1 () test_s)\n"); log(" (declare-fun s2 () test_s)\n"); log("\n"); - log(" ; both states are valid and s2 follows s1\n"); - log(" (assert (test_c s1))\n"); - log(" (assert (test_c s2))\n"); + log(" ; state s2 is the successor of state s1\n"); log(" (assert (test_t s1 s2))\n"); log("\n"); - log(" ; we are looking for a solution with y non-zero in s1\n"); - log(" (assert (or (|test_n y 0| s1) (|test_n y 1| s1)\n"); - log(" (|test_n y 2| s1) (|test_n y 3| s1)))\n"); + log(" ; we are looking for a model with y non-zero in s1\n"); + log(" (assert (distinct (|test_n y| s1) #b0000))\n"); log("\n"); - log(" ; we are looking for a solution with y zero in s2\n"); - log(" (assert (not (or (|test_n y 0| s2) (|test_n y 1| s2)\n"); - log(" (|test_n y 2| s2) (|test_n y 3| s2))))\n"); + log(" ; we are looking for a model with y zero in s2\n"); + log(" (assert (= (|test_n y| s2) #b0000))\n"); log("\n"); - log(" ; is there such a solution?\n"); + log(" ; is there such a model?\n"); log(" (check-sat)\n"); log("\n"); log("The following yosys script will create a 'test.smt2' file for our proof:\n"); log("\n"); log(" read_verilog test.v\n"); log(" hierarchy; proc; techmap; opt -fast\n"); - log(" write_smt2 -template test.tpl test.smt2\n"); + log(" write_smt2 -bv -tpl test.tpl test.smt2\n"); log("\n"); log("Running 'cvc4 test.smt2' will print 'unsat' because y can never transition\n"); log("from non-zero to zero in the test design.\n"); @@ -296,17 +271,23 @@ struct Smt2Backend : public Backend { virtual void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) { std::ifstream template_f; + bool bvmode = false; + log_header("Executing SMT2 backend.\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-template" && argidx+1 < args.size()) { + if (args[argidx] == "-tpl" && argidx+1 < args.size()) { template_f.open(args[++argidx]); if (template_f.fail()) log_error("Can't open template file `%s'.\n", args[argidx].c_str()); continue; } + if (args[argidx] == "-bv") { + bvmode = true; + continue; + } break; } extra_args(f, filename, args, argidx); @@ -332,7 +313,7 @@ struct Smt2Backend : public Backend { log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module)); - Smt2Worker worker(module); + Smt2Worker worker(module, bvmode); worker.run(); worker.write(*f); } From 95f17dbab0a15096c66e98af2d611b09ad26f3ea Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 25 Dec 2014 15:37:02 +0100 Subject: [PATCH 174/492] Added support for most BV cell types to write_smt2 --- backends/smt2/smt2.cc | 235 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 221 insertions(+), 14 deletions(-) diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index bad7b9b03..a5c015918 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -69,12 +69,40 @@ struct Smt2Worker fcache[bit] = std::pair(id, -1); } + void register_bv(RTLIL::SigSpec sig, int id) + { + log_assert(bvmode); + sigmap.apply(sig); + + log_assert(bvsizes.count(id) == 0); + bvsizes[id] = GetSize(sig); + + for (int i = 0; i < GetSize(sig); i++) { + log_assert(fcache.count(sig[i]) == 0); + fcache[sig[i]] = std::pair(id, i); + } + } + + void register_boolvec(RTLIL::SigSpec sig, int id) + { + log_assert(bvmode); + sigmap.apply(sig); + register_bool(sig[0], id); + + for (int i = 1; i < GetSize(sig); i++) + sigmap.add(sig[i], RTLIL::State::S0); + } + std::string get_bool(RTLIL::SigBit bit, const char *state_name = "state") { sigmap.apply(bit); + if (bit.wire == nullptr) + return bit == RTLIL::State::S1 ? "true" : "false"; + if (bit_driver.count(bit)) export_cell(bit_driver.at(bit)); + sigmap.apply(bit); if (fcache.count(bit) == 0) { decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) Bool) ; %s\n", @@ -83,16 +111,68 @@ struct Smt2Worker } auto f = fcache.at(bit); - log_assert(f.second == -1); + if (f.second >= 0) + return stringf("(= ((_ extract %d %d) (|%s#%d| %s)) #b1)", f.second, f.second, log_id(module), f.first, state_name); return stringf("(|%s#%d| %s)", log_id(module), f.first, state_name); } + std::string get_bool(RTLIL::SigSpec sig, const char *state_name = "state") + { + return get_bool(sig.to_single_sigbit(), state_name); + } + std::string get_bv(RTLIL::SigSpec sig, const char *state_name = "state") { + log_assert(bvmode); + sigmap.apply(sig); + std::vector subexpr; for (auto bit : sig) - subexpr.push_back(stringf("(ite %s #b1 #b0)", get_bool(bit, state_name).c_str())); + if (bit_driver.count(bit)) + export_cell(bit_driver.at(bit)); + sigmap.apply(sig); + + for (int i = 0, j = 1; i < GetSize(sig); i += j) + { + if (sig[i].wire == nullptr) { + while (i+j < GetSize(sig) && sig[i+j].wire == nullptr) j++; + subexpr.push_back("#b"); + for (int k = i+j-1; k >= i; k--) + subexpr.back() += sig[k] == RTLIL::State::S1 ? "1" : "0"; + continue; + } + + if (fcache.count(sig[i]) && fcache.at(sig[i]).second == -1) { + subexpr.push_back(stringf("(ite %s #b1 #b0)", get_bool(sig[i], state_name).c_str())); + continue; + } + + if (fcache.count(sig[i])) { + auto t1 = fcache.at(sig[i]); + while (i+j < GetSize(sig)) { + if (fcache.count(sig[i+j]) == 0) + break; + auto t2 = fcache.at(sig[i+j]); + if (t1.first != t2.first) + break; + if (t1.second+j != t2.second) + break; + j++; + } + if (t1.second == 0 && j == bvsizes.at(t1.first)) + subexpr.push_back(stringf("(|%s#%d| state)", log_id(module), t1.first)); + else + subexpr.push_back(stringf("((_ extract %d %d) (|%s#%d| state))", t1.second + j - 1, t1.second, log_id(module), t1.first)); + continue; + } + + while (i+j < GetSize(sig) && sig[i+j].wire && !fcache.count(sig[i+j])) j++; + decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) (_ BitVec %d)) ; %s\n", + log_id(module), idcounter, log_id(module), j, log_signal(sig.extract(i, j)))); + subexpr.push_back(stringf("(|%s#%d| state)", log_id(module), idcounter)); + register_bv(sig.extract(i, j), idcounter++); + } if (GetSize(subexpr) > 1) { std::string expr = "(concat"; @@ -107,15 +187,15 @@ struct Smt2Worker void export_gate(RTLIL::Cell *cell, std::string expr) { - RTLIL::SigBit bit = sigmap(cell->getPort("\\Y")[0]); + RTLIL::SigBit bit = sigmap(cell->getPort("\\Y").to_single_sigbit()); std::string processed_expr; for (char ch : expr) { - if (ch == 'A') processed_expr += get_bool(cell->getPort("\\A")[0]); - else if (ch == 'B') processed_expr += get_bool(cell->getPort("\\B")[0]); - else if (ch == 'C') processed_expr += get_bool(cell->getPort("\\C")[0]); - else if (ch == 'D') processed_expr += get_bool(cell->getPort("\\D")[0]); - else if (ch == 'S') processed_expr += get_bool(cell->getPort("\\S")[0]); + if (ch == 'A') processed_expr += get_bool(cell->getPort("\\A")); + else if (ch == 'B') processed_expr += get_bool(cell->getPort("\\B")); + else if (ch == 'C') processed_expr += get_bool(cell->getPort("\\C")); + else if (ch == 'D') processed_expr += get_bool(cell->getPort("\\D")); + else if (ch == 'S') processed_expr += get_bool(cell->getPort("\\S")); else processed_expr += ch; } @@ -125,6 +205,66 @@ struct Smt2Worker return; } + void export_bvop(RTLIL::Cell *cell, std::string expr, bool shift_op = false) + { + RTLIL::SigSpec sig_a, sig_b; + RTLIL::SigSpec sig_y = sigmap(cell->getPort("\\Y")); + bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); + int width = GetSize(sig_y); + + if (shift_op) { + width = std::max(width, GetSize(sig_a)); + width = std::max(width, GetSize(sig_b)); + } + + if (cell->hasPort("\\A")) { + sig_a = cell->getPort("\\A"); + sig_a.extend_u0(width, is_signed); + } + + if (cell->hasPort("\\B")) { + sig_b = cell->getPort("\\B"); + sig_b.extend_u0(width, is_signed && !shift_op); + } + + std::string processed_expr; + + 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 == 'L') processed_expr += is_signed ? "a" : "l"; + else if (ch == 'U') processed_expr += is_signed ? "" : "u"; + else processed_expr += ch; + } + + if (width != GetSize(sig_y)) + processed_expr = stringf("((_ extract %d 0) %s)", GetSize(sig_y)-1, processed_expr.c_str()); + + decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", + log_id(module), idcounter, log_id(module), GetSize(sig_y), processed_expr.c_str(), log_signal(sig_y))); + register_bv(sig_y, idcounter++); + return; + } + + void export_reduce(RTLIL::Cell *cell, std::string expr) + { + RTLIL::SigSpec sig_y = sigmap(cell->getPort("\\Y")); + std::string processed_expr; + + for (char ch : expr) + if (ch == 'A' || ch == 'B') { + RTLIL::SigSpec sig = sigmap(cell->getPort(stringf("\\%c", ch))); + for (auto bit : sig) + processed_expr += " " + get_bool(bit); + } else + processed_expr += ch; + + decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n", + log_id(module), idcounter, log_id(module), processed_expr.c_str(), log_signal(sig_y))); + register_boolvec(sig_y, idcounter++); + return; + } + void export_cell(RTLIL::Cell *cell) { if (exported_cells.count(cell)) @@ -133,8 +273,8 @@ struct Smt2Worker if (cell->type == "$_DFF_P_" || cell->type == "$_DFF_N_") { - std::string expr_d = get_bool(cell->getPort("\\D")[0]); - std::string expr_q = get_bool(cell->getPort("\\Q")[0], "next_state"); + std::string expr_d = get_bool(cell->getPort("\\D")); + std::string expr_q = get_bool(cell->getPort("\\Q"), "next_state"); trans.push_back(stringf(" (= %s %s)\n", expr_d.c_str(), expr_q.c_str())); return; } @@ -153,6 +293,64 @@ struct Smt2Worker if (cell->type == "$_AOI4_") return export_gate(cell, "(not (or (and A B) (and C D)))"); if (cell->type == "$_OAI4_") return export_gate(cell, "(not (and (or A B) (or C D)))"); + // FIXME: $lut $assert + + if (!bvmode) + log_error("Unsupported cell type %s for cell %s.%s. (Maybe this cell type would be supported in -bv mode?)\n", + log_id(cell->type), log_id(module), log_id(cell)); + + if (cell->type == "$dff") + { + std::string expr_d = get_bv(cell->getPort("\\D")); + std::string expr_q = get_bv(cell->getPort("\\Q"), "next_state"); + trans.push_back(stringf(" (= %s %s)\n", expr_d.c_str(), expr_q.c_str())); + return; + } + + if (cell->type == "$and") return export_bvop(cell, "(bvand A B)"); + if (cell->type == "$or") return export_bvop(cell, "(bvor A B)"); + if (cell->type == "$xor") return export_bvop(cell, "(bvxor A B)"); + if (cell->type == "$xnor") return export_bvop(cell, "(bvxnor A B)"); + + if (cell->type == "$shl") return export_bvop(cell, "(bvshl A B)", true); + if (cell->type == "$shr") return export_bvop(cell, "(bvlshr A B)", true); + if (cell->type == "$sshl") return export_bvop(cell, "(bvshl A B)", true); + if (cell->type == "$sshr") return export_bvop(cell, "(bvLshr A B)", true); + + // FIXME: $shift $shiftx + + if (cell->type == "$lt") return export_bvop(cell, "(bvUlt A B)"); + if (cell->type == "$le") return export_bvop(cell, "(bvUle A B)"); + if (cell->type == "$ge") return export_bvop(cell, "(bvUge A B)"); + if (cell->type == "$gt") return export_bvop(cell, "(bvUgt A B)"); + + if (cell->type == "$ne") return export_bvop(cell, "(distinct A B)"); + if (cell->type == "$nex") return export_bvop(cell, "(distinct A B)"); + if (cell->type == "$eq") return export_bvop(cell, "(= A B)"); + if (cell->type == "$eqx") return export_bvop(cell, "(= A B)"); + + if (cell->type == "$not") return export_bvop(cell, "(bvnot A)"); + if (cell->type == "$pos") return export_bvop(cell, "A"); + if (cell->type == "$neg") return export_bvop(cell, "(bvneg A)"); + + if (cell->type == "$add") return export_bvop(cell, "(bvadd A B)"); + if (cell->type == "$sub") return export_bvop(cell, "(bvsub A B)"); + if (cell->type == "$mul") return export_bvop(cell, "(bvmul A B)"); + if (cell->type == "$div") return export_bvop(cell, "(bvUdiv A B)"); + if (cell->type == "$mod") return export_bvop(cell, "(bvUrem A B)"); + + if (cell->type == "$reduce_and") return export_reduce(cell, "(and A)"); + if (cell->type == "$reduce_or") return export_reduce(cell, "(or A)"); + if (cell->type == "$reduce_xor") return export_reduce(cell, "(xor A)"); + if (cell->type == "$reduce_xnor") return export_reduce(cell, "(not (xor A))"); + if (cell->type == "$reduce_bool") return export_reduce(cell, "(or A)"); + + if (cell->type == "$logic_not") return export_reduce(cell, "(not (or A))"); + if (cell->type == "$logic_and") return export_reduce(cell, "(and (or A) (or B))"); + if (cell->type == "$logic_or") return export_reduce(cell, "(or A B)"); + + // FIXME: $slice $concat $mux $pmux + log_error("Unsupported cell type %s for cell %s.%s.\n", log_id(cell->type), log_id(module), log_id(cell)); } @@ -181,10 +379,19 @@ struct Smt2Worker { for (auto it : decls) f << it; - f << stringf("(define-fun |%s_t| ((state |%s_s|)(next_state |%s_s|)) Bool (and\n", log_id(module), log_id(module), log_id(module)); - for (auto it : trans) - f << it; - f << "true true))\n"; + + f << stringf("(define-fun |%s_t| ((state |%s_s|) (next_state |%s_s|)) Bool ", log_id(module), log_id(module), log_id(module)); + if (GetSize(trans) > 1) { + f << "(and\n"; + for (auto it : trans) + f << it; + f << "))"; + } else + if (GetSize(trans) == 1) + f << "\n" + trans.front() + ")"; + else + f << "true)"; + f << stringf(" ; end of module %s\n", log_id(module)); } }; From 170788a3decdf8b475762106df24eae910cf24c7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 25 Dec 2014 16:41:20 +0100 Subject: [PATCH 175/492] Fixed simplemap for $ne cells with output width > 1 --- passes/techmap/simplemap.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index 694ebf226..9cea5f45d 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -241,18 +241,19 @@ void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell) RTLIL::SigSpec xor_out = module->addWire(NEW_ID, std::max(GetSize(sig_a), GetSize(sig_b))); RTLIL::Cell *xor_cell = module->addXor(NEW_ID, sig_a, sig_b, xor_out, is_signed); - - RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID); - RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID, xor_out, reduce_out); - - if (!is_ne) - module->addNotGate(NEW_ID, reduce_out, sig_y); - simplemap_bitop(module, xor_cell); module->remove(xor_cell); + RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID); + RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID, xor_out, reduce_out); simplemap_reduce(module, reduce_cell); module->remove(reduce_cell); + + if (!is_ne) { + RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID, reduce_out, sig_y); + simplemap_lognot(module, not_cell); + module->remove(not_cell); + } } void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell) From 7dece74fae69e80349f9848ea2b9a09252de2c23 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 25 Dec 2014 17:04:13 +0100 Subject: [PATCH 176/492] Added "test_cell -w" feature --- passes/tests/test_cell.cc | 57 ++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index 3406d7e3e..f0d19b6bb 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -508,7 +508,7 @@ struct TestCellPass : public Pass { log("by comparing SAT solver, EVAL and TECHMAP implementations of the cell types..\n"); log("\n"); log("Run with 'all' instead of a cell type to run the test on all supported\n"); - log("cell types.\n"); + log("cell types. Use for example 'all /$add' for all cell types except $add.\n"); log("\n"); log(" -n {integer}\n"); log(" create this number of cell instances and test them (default = 100).\n"); @@ -519,6 +519,10 @@ struct TestCellPass : public Pass { log(" -f {ilang_file}\n"); log(" don't generate circuits. instead load the specified ilang file.\n"); log("\n"); + log(" -w {filename_prefix}\n"); + log(" don't test anything. just generate the circuits and write them\n"); + log(" to ilang files with the specified prefix\n"); + log("\n"); log(" -map {filename}\n"); log(" pass this option to techmap.\n"); log("\n"); @@ -545,7 +549,7 @@ struct TestCellPass : public Pass { { int num_iter = 100; std::string techmap_cmd = "techmap -assert"; - std::string ilang_file; + std::string ilang_file, write_prefix; xorshift32_state = 0; std::ofstream vlog_file; bool verbose = false; @@ -572,6 +576,10 @@ struct TestCellPass : public Pass { num_iter = 1; continue; } + if (args[argidx] == "-w" && argidx+1 < GetSize(args)) { + write_prefix = args[++argidx]; + continue; + } if (args[argidx] == "-script" && argidx+1 < GetSize(args)) { techmap_cmd = "script " + args[++argidx]; continue; @@ -675,6 +683,15 @@ struct TestCellPass : public Pass { continue; } + if (args[argidx].substr(0, 1) == "/") { + std::vector new_selected_cell_types; + for (auto it : selected_cell_types) + if (it != args[argidx].substr(1)) + new_selected_cell_types.push_back(it); + new_selected_cell_types.swap(selected_cell_types); + continue; + } + if (cell_types.count(args[argidx]) == 0) { std::string cell_type_list; int charcount = 100; @@ -713,23 +730,27 @@ struct TestCellPass : public Pass { Frontend::frontend_call(design, NULL, std::string(), "ilang " + ilang_file); else create_gold_module(design, cell_type, cell_types.at(cell_type), constmode); - Pass::call(design, stringf("copy gold gate; cd gate; %s; cd ..; opt -fast gate", techmap_cmd.c_str())); - if (!nosat) - Pass::call(design, "miter -equiv -flatten -make_outputs -ignore_gold_x gold gate miter"); - if (verbose) - Pass::call(design, "dump gate"); - Pass::call(design, "dump gold"); - if (!nosat) - Pass::call(design, "sat -verify -enable_undef -prove trigger 0 -show-inputs -show-outputs miter"); - std::string uut_name = stringf("uut_%s_%d", cell_type.substr(1).c_str(), i); - if (vlog_file.is_open()) { - Pass::call(design, stringf("copy gold %s_expr; select %s_expr", uut_name.c_str(), uut_name.c_str())); - Backend::backend_call(design, &vlog_file, "", "verilog -selected"); - Pass::call(design, stringf("copy gold %s_noexpr; select %s_noexpr", uut_name.c_str(), uut_name.c_str())); - Backend::backend_call(design, &vlog_file, "", "verilog -selected -noexpr"); - uut_names.push_back(uut_name); + if (!write_prefix.empty()) { + Pass::call(design, stringf("write_ilang %s_%s_%05d.il", write_prefix.c_str(), cell_type.c_str()+1, i)); + } else { + Pass::call(design, stringf("copy gold gate; cd gate; %s; cd ..; opt -fast gate", techmap_cmd.c_str())); + if (!nosat) + Pass::call(design, "miter -equiv -flatten -make_outputs -ignore_gold_x gold gate miter"); + if (verbose) + Pass::call(design, "dump gate"); + Pass::call(design, "dump gold"); + if (!nosat) + Pass::call(design, "sat -verify -enable_undef -prove trigger 0 -show-inputs -show-outputs miter"); + std::string uut_name = stringf("uut_%s_%d", cell_type.substr(1).c_str(), i); + if (vlog_file.is_open()) { + Pass::call(design, stringf("copy gold %s_expr; select %s_expr", uut_name.c_str(), uut_name.c_str())); + Backend::backend_call(design, &vlog_file, "", "verilog -selected"); + Pass::call(design, stringf("copy gold %s_noexpr; select %s_noexpr", uut_name.c_str(), uut_name.c_str())); + Backend::backend_call(design, &vlog_file, "", "verilog -selected -noexpr"); + uut_names.push_back(uut_name); + } + run_eval_test(design, verbose, nosat, uut_name, vlog_file); } - run_eval_test(design, verbose, nosat, uut_name, vlog_file); delete design; } From 68233baa1f3d6e3dcfec20583b0f37202035a589 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 25 Dec 2014 17:52:31 +0100 Subject: [PATCH 177/492] Various fixes and improvements in write_smt2 --- backends/smt2/smt2.cc | 75 +++++++++++++++++++++---------------- backends/smt2/test_cells.sh | 45 ++++++++++++++++++++++ 2 files changed, 88 insertions(+), 32 deletions(-) create mode 100644 backends/smt2/test_cells.sh diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index a5c015918..c383bbab9 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -133,7 +133,7 @@ struct Smt2Worker export_cell(bit_driver.at(bit)); sigmap.apply(sig); - for (int i = 0, j = 1; i < GetSize(sig); i += j) + for (int i = 0, j = 1; i < GetSize(sig); i += j, j = 1) { if (sig[i].wire == nullptr) { while (i+j < GetSize(sig) && sig[i+j].wire == nullptr) j++; @@ -167,7 +167,10 @@ struct Smt2Worker continue; } - while (i+j < GetSize(sig) && sig[i+j].wire && !fcache.count(sig[i+j])) j++; + std::set seen_bits = { sig[i] }; + while (i+j < GetSize(sig) && sig[i+j].wire && !fcache.count(sig[i+j]) && !seen_bits.count(sig[i+j])) + seen_bits.insert(sig[i+j]), j++; + decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) (_ BitVec %d)) ; %s\n", log_id(module), idcounter, log_id(module), j, log_signal(sig.extract(i, j)))); subexpr.push_back(stringf("(|%s#%d| state)", log_id(module), idcounter)); @@ -205,14 +208,14 @@ struct Smt2Worker return; } - void export_bvop(RTLIL::Cell *cell, std::string expr, bool shift_op = false) + void export_bvop(RTLIL::Cell *cell, std::string expr, char type = 0) { RTLIL::SigSpec sig_a, sig_b; RTLIL::SigSpec sig_y = sigmap(cell->getPort("\\Y")); bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); int width = GetSize(sig_y); - if (shift_op) { + if (type == 's') { width = std::max(width, GetSize(sig_a)); width = std::max(width, GetSize(sig_b)); } @@ -224,7 +227,7 @@ struct Smt2Worker if (cell->hasPort("\\B")) { sig_b = cell->getPort("\\B"); - sig_b.extend_u0(width, is_signed && !shift_op); + sig_b.extend_u0(width, is_signed && !(type == 's')); } std::string processed_expr; @@ -233,20 +236,26 @@ struct Smt2Worker if (ch == 'A') processed_expr += get_bv(sig_a); else if (ch == 'B') processed_expr += get_bv(sig_b); else if (ch == 'L') processed_expr += is_signed ? "a" : "l"; - else if (ch == 'U') processed_expr += is_signed ? "" : "u"; + else if (ch == 'U') processed_expr += is_signed ? "s" : "u"; else processed_expr += ch; } if (width != GetSize(sig_y)) processed_expr = stringf("((_ extract %d 0) %s)", GetSize(sig_y)-1, processed_expr.c_str()); - decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", - log_id(module), idcounter, log_id(module), GetSize(sig_y), processed_expr.c_str(), log_signal(sig_y))); - register_bv(sig_y, idcounter++); + if (type == 'b') { + decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n", + log_id(module), idcounter, log_id(module), processed_expr.c_str(), log_signal(sig_y))); + register_boolvec(sig_y, idcounter++); + } else { + decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", + log_id(module), idcounter, log_id(module), GetSize(sig_y), processed_expr.c_str(), log_signal(sig_y))); + register_bv(sig_y, idcounter++); + } return; } - void export_reduce(RTLIL::Cell *cell, std::string expr) + void export_reduce(RTLIL::Cell *cell, std::string expr, bool identity_val) { RTLIL::SigSpec sig_y = sigmap(cell->getPort("\\Y")); std::string processed_expr; @@ -256,6 +265,8 @@ struct Smt2Worker RTLIL::SigSpec sig = sigmap(cell->getPort(stringf("\\%c", ch))); for (auto bit : sig) processed_expr += " " + get_bool(bit); + if (GetSize(sig) == 1) + processed_expr += identity_val ? " true" : " false"; } else processed_expr += ch; @@ -312,22 +323,22 @@ struct Smt2Worker if (cell->type == "$xor") return export_bvop(cell, "(bvxor A B)"); if (cell->type == "$xnor") return export_bvop(cell, "(bvxnor A B)"); - if (cell->type == "$shl") return export_bvop(cell, "(bvshl A B)", true); - if (cell->type == "$shr") return export_bvop(cell, "(bvlshr A B)", true); - if (cell->type == "$sshl") return export_bvop(cell, "(bvshl A B)", true); - if (cell->type == "$sshr") return export_bvop(cell, "(bvLshr A B)", true); + if (cell->type == "$shl") return export_bvop(cell, "(bvshl A B)", 's'); + if (cell->type == "$shr") return export_bvop(cell, "(bvlshr A B)", 's'); + if (cell->type == "$sshl") return export_bvop(cell, "(bvshl A B)", 's'); + if (cell->type == "$sshr") return export_bvop(cell, "(bvLshr A B)", 's'); // FIXME: $shift $shiftx - if (cell->type == "$lt") return export_bvop(cell, "(bvUlt A B)"); - if (cell->type == "$le") return export_bvop(cell, "(bvUle A B)"); - if (cell->type == "$ge") return export_bvop(cell, "(bvUge A B)"); - if (cell->type == "$gt") return export_bvop(cell, "(bvUgt A B)"); + if (cell->type == "$lt") return export_bvop(cell, "(bvUlt A B)", 'b'); + if (cell->type == "$le") return export_bvop(cell, "(bvUle A B)", 'b'); + if (cell->type == "$ge") return export_bvop(cell, "(bvUge A B)", 'b'); + if (cell->type == "$gt") return export_bvop(cell, "(bvUgt A B)", 'b'); - if (cell->type == "$ne") return export_bvop(cell, "(distinct A B)"); - if (cell->type == "$nex") return export_bvop(cell, "(distinct A B)"); - if (cell->type == "$eq") return export_bvop(cell, "(= A B)"); - if (cell->type == "$eqx") return export_bvop(cell, "(= A B)"); + if (cell->type == "$ne") return export_bvop(cell, "(distinct A B)", 'b'); + if (cell->type == "$nex") return export_bvop(cell, "(distinct A B)", 'b'); + if (cell->type == "$eq") return export_bvop(cell, "(= A B)", 'b'); + if (cell->type == "$eqx") return export_bvop(cell, "(= A B)", 'b'); if (cell->type == "$not") return export_bvop(cell, "(bvnot A)"); if (cell->type == "$pos") return export_bvop(cell, "A"); @@ -339,15 +350,15 @@ struct Smt2Worker if (cell->type == "$div") return export_bvop(cell, "(bvUdiv A B)"); if (cell->type == "$mod") return export_bvop(cell, "(bvUrem A B)"); - if (cell->type == "$reduce_and") return export_reduce(cell, "(and A)"); - if (cell->type == "$reduce_or") return export_reduce(cell, "(or A)"); - if (cell->type == "$reduce_xor") return export_reduce(cell, "(xor A)"); - if (cell->type == "$reduce_xnor") return export_reduce(cell, "(not (xor A))"); - if (cell->type == "$reduce_bool") return export_reduce(cell, "(or A)"); + if (cell->type == "$reduce_and") return export_reduce(cell, "(and A)", true); + if (cell->type == "$reduce_or") return export_reduce(cell, "(or A)", false); + if (cell->type == "$reduce_xor") return export_reduce(cell, "(xor A)", false); + if (cell->type == "$reduce_xnor") return export_reduce(cell, "(not (xor A))", false); + if (cell->type == "$reduce_bool") return export_reduce(cell, "(or A)", false); - if (cell->type == "$logic_not") return export_reduce(cell, "(not (or A))"); - if (cell->type == "$logic_and") return export_reduce(cell, "(and (or A) (or B))"); - if (cell->type == "$logic_or") return export_reduce(cell, "(or A B)"); + if (cell->type == "$logic_not") return export_reduce(cell, "(not (or A))", false); + 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); // FIXME: $slice $concat $mux $pmux @@ -407,8 +418,8 @@ struct Smt2Backend : public Backend { log("'' this will declare the sort '_s' (state of the module) and the the\n"); log("function '_t' (state transition function).\n"); log("\n"); - log("The '_s' sort represents the a module state. Additional '_n' functions\n"); - log("are provided that can be used to access the values of all signals in the module.\n"); + log("The '_s' sort represents a module state. Additional '_n' functions\n"); + log("are provided that can be used to access the values of the signals in the module.\n"); log("Only ports, and signals with the 'keep' attribute set are made available via\n"); log("such functions. Without the -bv option, multi-bit wires are exported as\n"); log("separate functions of type Bool for the individual bits. With the -bv option\n"); diff --git a/backends/smt2/test_cells.sh b/backends/smt2/test_cells.sh new file mode 100644 index 000000000..28d5c57f5 --- /dev/null +++ b/backends/smt2/test_cells.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +set -ex + +rm -rf test_cells +mkdir test_cells +cd test_cells + +../../../yosys -p 'test_cell -n 2 -w test all /$alu /$macc /$fa /$lcu /$lut /$shift /$shiftx /$div /$mod' + +cat > miter.tpl <<- EOT +; #model# (set-option :produce-models true) +(set-logic QF_UFBV) +%% +(declare-fun s () miter_s) +(assert (|miter_n trigger| s)) +(check-sat) +; #model# (get-value ((|miter_n in_A| s) (|miter_n in_B| s) (|miter_n gold_Y| s) (|miter_n gate_Y| s) (|miter_n trigger| s))) +EOT + +for x in test_*.il; do + x=${x%.il} + cat > $x.ys <<- EOT + read_ilang $x.il + copy gold gate + + cd gate + techmap; opt; abc;; + cd .. + + miter -equiv -flatten -make_outputs gold gate miter + hierarchy -check -top miter + + dump + write_smt2 -bv -tpl miter.tpl $x.smt2 + EOT + ../../../yosys $x.ys + cvc4 $x.smt2 > $x.result + if ! grep unsat $x.result; then + echo "Proof failed! Extracting model..." + sed -i 's/^; #model# //' $x.smt2 + cvc4 $x.smt2 + exit 1 + fi +done From b748622a7f482cebc44c93ee065f36b159bb2a6c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 25 Dec 2014 19:22:39 +0100 Subject: [PATCH 178/492] Added "test_cell -muxdiv" --- passes/tests/test_cell.cc | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index f0d19b6bb..ea2ab1e65 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -36,7 +36,7 @@ static uint32_t xorshift32(uint32_t limit) { return xorshift32_state % limit; } -static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, std::string cell_type_flags, bool constmode) +static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, std::string cell_type_flags, bool constmode, bool muxdiv) { RTLIL::Module *module = design->addModule("\\gold"); RTLIL::Cell *cell = module->addCell("\\UUT", cell_type); @@ -202,6 +202,13 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, cell->setPort("\\Y", wire); } + if (muxdiv && (cell_type == "$div" || cell_type == "$mod")) { + auto b_not_zero = module->ReduceBool(NEW_ID, cell->getPort("\\B")); + auto div_out = module->addWire(NEW_ID, GetSize(cell->getPort("\\Y"))); + module->addMux(NEW_ID, RTLIL::SigSpec(0, GetSize(div_out)), div_out, b_not_zero, cell->getPort("\\Y")); + cell->setPort("\\Y", div_out); + } + if (cell_type == "$alu") { wire = module->addWire("\\CI"); @@ -529,6 +536,10 @@ struct TestCellPass : public Pass { log(" -simlib\n"); log(" use \"techmap -map +/simlib.v -max_iter 2 -autoproc\"\n"); log("\n"); + log(" -muxdiv\n"); + log(" when creating test benches with dividers, create an additional mux\n"); + log(" to mask out the division-by-zero case\n"); + log("\n"); log(" -script {script_file}\n"); log(" instead of calling \"techmap\", call \"script {script_file}\".\n"); log("\n"); @@ -552,6 +563,7 @@ struct TestCellPass : public Pass { std::string ilang_file, write_prefix; xorshift32_state = 0; std::ofstream vlog_file; + bool muxdiv = false; bool verbose = false; bool constmode = false; bool nosat = false; @@ -588,6 +600,10 @@ struct TestCellPass : public Pass { techmap_cmd = "techmap -map +/simlib.v -max_iter 2 -autoproc"; continue; } + if (args[argidx] == "-muxdiv") { + muxdiv = true; + continue; + } if (args[argidx] == "-const") { constmode = true; continue; @@ -729,7 +745,7 @@ struct TestCellPass : public Pass { if (cell_type == "ilang") Frontend::frontend_call(design, NULL, std::string(), "ilang " + ilang_file); else - create_gold_module(design, cell_type, cell_types.at(cell_type), constmode); + create_gold_module(design, cell_type, cell_types.at(cell_type), constmode, muxdiv); if (!write_prefix.empty()) { Pass::call(design, stringf("write_ilang %s_%s_%05d.il", write_prefix.c_str(), cell_type.c_str()+1, i)); } else { From e8c12e5f0c49cca4dd54da12003bd010a488aee3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 25 Dec 2014 20:28:16 +0100 Subject: [PATCH 179/492] Various fixes and improvements in "write_smt2 -bv" --- backends/smt2/.gitignore | 1 + backends/smt2/smt2.cc | 35 ++++++++++++++++++++++++++++------- backends/smt2/test_cells.sh | 18 ++++++++++++++---- 3 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 backends/smt2/.gitignore diff --git a/backends/smt2/.gitignore b/backends/smt2/.gitignore new file mode 100644 index 000000000..313ea0a1a --- /dev/null +++ b/backends/smt2/.gitignore @@ -0,0 +1 @@ +test_cells diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index c383bbab9..8451eff4f 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -215,9 +215,9 @@ struct Smt2Worker bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); int width = GetSize(sig_y); - if (type == 's') { - width = std::max(width, GetSize(sig_a)); - width = std::max(width, GetSize(sig_b)); + if (type == 's' || type == 'd' || type == 'b') { + width = std::max(width, GetSize(cell->getPort("\\A"))); + width = std::max(width, GetSize(cell->getPort("\\B"))); } if (cell->hasPort("\\A")) { @@ -240,7 +240,7 @@ struct Smt2Worker else processed_expr += ch; } - if (width != GetSize(sig_y)) + if (width != GetSize(sig_y) && type != 'b') processed_expr = stringf("((_ extract %d 0) %s)", GetSize(sig_y)-1, processed_expr.c_str()); if (type == 'b') { @@ -347,8 +347,8 @@ struct Smt2Worker if (cell->type == "$add") return export_bvop(cell, "(bvadd A B)"); if (cell->type == "$sub") return export_bvop(cell, "(bvsub A B)"); if (cell->type == "$mul") return export_bvop(cell, "(bvmul A B)"); - if (cell->type == "$div") return export_bvop(cell, "(bvUdiv A B)"); - if (cell->type == "$mod") return export_bvop(cell, "(bvUrem A B)"); + if (cell->type == "$div") return export_bvop(cell, "(bvUdiv A B)", 'd'); + if (cell->type == "$mod") return export_bvop(cell, "(bvUrem A B)", 'd'); if (cell->type == "$reduce_and") return export_reduce(cell, "(and A)", true); if (cell->type == "$reduce_or") return export_reduce(cell, "(or A)", false); @@ -360,7 +360,28 @@ 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); - // FIXME: $slice $concat $mux $pmux + if (cell->type == "$mux" || cell->type == "$pmux") + { + int width = GetSize(cell->getPort("\\Y")); + std::string processed_expr = get_bv(cell->getPort("\\A")); + + RTLIL::SigSpec sig_b = cell->getPort("\\B"); + RTLIL::SigSpec sig_s = cell->getPort("\\S"); + get_bv(sig_b); + get_bv(sig_s); + + for (int i = 0; i < GetSize(sig_s); i++) + processed_expr = stringf("(ite %s %s %s)", get_bool(sig_s[i]).c_str(), + get_bv(sig_b.extract(i*width, width)).c_str(), processed_expr.c_str()); + + RTLIL::SigSpec sig = sigmap(cell->getPort("\\Y")); + decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", + log_id(module), idcounter, log_id(module), width, processed_expr.c_str(), log_signal(sig))); + register_bv(sig, idcounter++); + return; + } + + // FIXME: $slice $concat log_error("Unsupported cell type %s for cell %s.%s.\n", log_id(cell->type), log_id(module), log_id(cell)); diff --git a/backends/smt2/test_cells.sh b/backends/smt2/test_cells.sh index 28d5c57f5..34adb7af3 100644 --- a/backends/smt2/test_cells.sh +++ b/backends/smt2/test_cells.sh @@ -6,7 +6,7 @@ rm -rf test_cells mkdir test_cells cd test_cells -../../../yosys -p 'test_cell -n 2 -w test all /$alu /$macc /$fa /$lcu /$lut /$shift /$shiftx /$div /$mod' +../../../yosys -p 'test_cell -muxdiv -w test all /$alu /$macc /$fa /$lcu /$lut /$shift /$shiftx' cat > miter.tpl <<- EOT ; #model# (set-option :produce-models true) @@ -18,7 +18,7 @@ cat > miter.tpl <<- EOT ; #model# (get-value ((|miter_n in_A| s) (|miter_n in_B| s) (|miter_n gold_Y| s) (|miter_n gate_Y| s) (|miter_n trigger| s))) EOT -for x in test_*.il; do +for x in $(set +x; ls test_*.il | sort -R); do x=${x%.il} cat > $x.ys <<- EOT read_ilang $x.il @@ -34,8 +34,11 @@ for x in test_*.il; do dump write_smt2 -bv -tpl miter.tpl $x.smt2 EOT - ../../../yosys $x.ys - cvc4 $x.smt2 > $x.result + ../../../yosys -q $x.ys + if ! cvc4 $x.smt2 > $x.result; then + cat $x.result + exit 1 + fi if ! grep unsat $x.result; then echo "Proof failed! Extracting model..." sed -i 's/^; #model# //' $x.smt2 @@ -43,3 +46,10 @@ for x in test_*.il; do exit 1 fi done + +set +x +echo "" +echo " All tests passed." +echo "" +exit 0 + From a6c96b986be313368b4fa03eba5cf6987448100c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 26 Dec 2014 10:53:21 +0100 Subject: [PATCH 180/492] Added Yosys::{dict,nodict,vector} container types --- backends/verilog/verilog_backend.cc | 2 +- frontends/ast/ast.cc | 2 +- frontends/ast/ast.h | 2 +- frontends/ilang/ilang_parser.y | 2 +- kernel/cost.h | 12 +- kernel/rtlil.cc | 100 +++-- kernel/rtlil.h | 620 ++++++++++++++++------------ kernel/yosys.h | 12 + passes/cmds/delete.cc | 8 +- passes/cmds/rename.cc | 8 +- passes/cmds/select.cc | 4 +- passes/cmds/setattr.cc | 2 +- passes/cmds/splitnets.cc | 2 +- passes/fsm/fsm_export.cc | 4 +- passes/hierarchy/hierarchy.cc | 4 +- passes/opt/opt_clean.cc | 2 +- passes/opt/opt_const.cc | 6 +- passes/opt/opt_share.cc | 18 +- passes/opt/wreduce.cc | 4 +- passes/techmap/extract.cc | 4 +- passes/techmap/techmap.cc | 8 +- 21 files changed, 495 insertions(+), 331 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 9e8342ab9..ffaf9ec07 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -246,7 +246,7 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig) } } -void dump_attributes(std::ostream &f, std::string indent, std::map &attributes, char term = '\n') +void dump_attributes(std::ostream &f, std::string indent, dict &attributes, char term = '\n') { if (noattr) return; diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 56ea64eff..0f79352f7 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1018,7 +1018,7 @@ AstModule::~AstModule() } // create a new parametric module (when needed) and return the name of the generated module -RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map parameters) +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters) { std::string stripped_name = name.str(); diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 023755387..27cf0ef3d 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -268,7 +268,7 @@ namespace AST AstNode *ast; bool nolatches, nomem2reg, mem2reg, lib, noopt, icells, autowire; virtual ~AstModule(); - virtual RTLIL::IdString derive(RTLIL::Design *design, std::map parameters); + virtual RTLIL::IdString derive(RTLIL::Design *design, dict parameters); virtual RTLIL::Module *clone() const; }; diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y index a5cc06898..4e0981b51 100644 --- a/frontends/ilang/ilang_parser.y +++ b/frontends/ilang/ilang_parser.y @@ -36,7 +36,7 @@ namespace ILANG_FRONTEND { RTLIL::Process *current_process; std::vector*> switch_stack; std::vector case_stack; - std::map attrbuf; + dict attrbuf; } using namespace ILANG_FRONTEND; YOSYS_NAMESPACE_END diff --git a/kernel/cost.h b/kernel/cost.h index 61a693b9c..1b4166e00 100644 --- a/kernel/cost.h +++ b/kernel/cost.h @@ -24,12 +24,12 @@ YOSYS_NAMESPACE_BEGIN -int get_cell_cost(RTLIL::Cell *cell, std::map *mod_cost_cache = nullptr); +int get_cell_cost(RTLIL::Cell *cell, dict *mod_cost_cache = nullptr); -int get_cell_cost(RTLIL::IdString type, const std::map ¶meters = std::map(), - RTLIL::Design *design = nullptr, std::map *mod_cost_cache = nullptr) +int get_cell_cost(RTLIL::IdString type, const dict ¶meters = dict(), + RTLIL::Design *design = nullptr, dict *mod_cost_cache = nullptr) { - static std::map gate_cost = { + static dict gate_cost = { { "$_BUF_", 1 }, { "$_NOT_", 2 }, { "$_AND_", 4 }, @@ -55,7 +55,7 @@ int get_cell_cost(RTLIL::IdString type, const std::mapattributes.count("\\cost")) return mod->attributes.at("\\cost").as_int(); - std::map local_mod_cost_cache; + dict local_mod_cost_cache; if (mod_cost_cache == nullptr) mod_cost_cache = &local_mod_cost_cache; @@ -74,7 +74,7 @@ int get_cell_cost(RTLIL::IdString type, const std::map *mod_cost_cache) +int get_cell_cost(RTLIL::Cell *cell, dict *mod_cost_cache) { return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache); } diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 0e8078df6..2d3d83f42 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -30,7 +30,7 @@ YOSYS_NAMESPACE_BEGIN RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard; std::vector RTLIL::IdString::global_refcount_storage_; std::vector RTLIL::IdString::global_id_storage_; -std::map RTLIL::IdString::global_id_index_; +dict RTLIL::IdString::global_id_index_; std::vector RTLIL::IdString::global_free_idx_list_; RTLIL::Const::Const() @@ -464,7 +464,7 @@ RTLIL::Module::~Module() delete it->second; } -RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, std::map) +RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict) { log_error("Module `%s' is used with parameters but is not parametric!\n", id2cstr(name)); } @@ -480,7 +480,7 @@ namespace { { RTLIL::Module *module; RTLIL::Cell *cell; - std::set expected_params, expected_ports; + nodict expected_params, expected_ports; InternalCellChecker(RTLIL::Module *module, RTLIL::Cell *cell) : module(module), cell(cell) { } @@ -1132,7 +1132,7 @@ namespace { struct DeleteWireWorker { RTLIL::Module *module; - const std::set *wires_p; + const nodict *wires_p; void operator()(RTLIL::SigSpec &sig) { std::vector chunks = sig; @@ -1146,16 +1146,7 @@ namespace { }; } -#if 0 -void RTLIL::Module::remove(RTLIL::Wire *wire) -{ - std::setPort wires_; - wires_.insert(wire); - remove(wires_); -} -#endif - -void RTLIL::Module::remove(const std::set &wires) +void RTLIL::Module::remove(const nodict &wires) { log_assert(refcount_wires_ == 0); @@ -1811,7 +1802,7 @@ const RTLIL::SigSpec &RTLIL::Cell::getPort(RTLIL::IdString portname) const return connections_.at(portname); } -const std::map &RTLIL::Cell::connections() const +const dict &RTLIL::Cell::connections() const { return connections_; } @@ -2178,6 +2169,17 @@ RTLIL::SigSpec::SigSpec(std::vector bits) check(); } +RTLIL::SigSpec::SigSpec(nodict bits) +{ + cover("kernel.rtlil.sigspec.init.stdset_bits"); + + width_ = 0; + hash_ = 0; + for (auto &bit : bits) + append_bit(bit); + check(); +} + RTLIL::SigSpec::SigSpec(std::set bits) { cover("kernel.rtlil.sigspec.init.stdset_bits"); @@ -2306,7 +2308,7 @@ void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec pattern.unpack(); with.unpack(); - std::map rules; + dict rules; for (int i = 0; i < GetSize(pattern.bits_); i++) if (pattern.bits_[i].wire != NULL) @@ -2315,6 +2317,30 @@ void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec replace(rules, other); } +void RTLIL::SigSpec::replace(const dict &rules) +{ + replace(rules, this); +} + +void RTLIL::SigSpec::replace(const dict &rules, RTLIL::SigSpec *other) const +{ + cover("kernel.rtlil.sigspec.replace_dict"); + + log_assert(other != NULL); + log_assert(width_ == other->width_); + + unpack(); + other->unpack(); + + for (int i = 0; i < GetSize(bits_); i++) { + auto it = rules.find(bits_[i]); + if (it != rules.end()) + other->bits_[i] = it->second; + } + + other->check(); +} + void RTLIL::SigSpec::replace(const std::map &rules) { replace(rules, this); @@ -2322,7 +2348,7 @@ void RTLIL::SigSpec::replace(const std::map &rules void RTLIL::SigSpec::replace(const std::map &rules, RTLIL::SigSpec *other) const { - cover("kernel.rtlil.sigspec.replace"); + cover("kernel.rtlil.sigspec.replace_map"); log_assert(other != NULL); log_assert(width_ == other->width_); @@ -2352,22 +2378,22 @@ void RTLIL::SigSpec::remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other void RTLIL::SigSpec::remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) { - std::set pattern_bits = pattern.to_sigbit_set(); + nodict pattern_bits = pattern.to_sigbit_nodict(); remove2(pattern_bits, other); } -void RTLIL::SigSpec::remove(const std::set &pattern) +void RTLIL::SigSpec::remove(const nodict &pattern) { remove2(pattern, NULL); } -void RTLIL::SigSpec::remove(const std::set &pattern, RTLIL::SigSpec *other) const +void RTLIL::SigSpec::remove(const nodict &pattern, RTLIL::SigSpec *other) const { RTLIL::SigSpec tmp = *this; tmp.remove2(pattern, other); } -void RTLIL::SigSpec::remove2(const std::set &pattern, RTLIL::SigSpec *other) +void RTLIL::SigSpec::remove2(const nodict &pattern, RTLIL::SigSpec *other) { if (other) cover("kernel.rtlil.sigspec.remove_other"); @@ -2413,11 +2439,11 @@ void RTLIL::SigSpec::remove2(const std::set &pattern, RTLIL::SigS RTLIL::SigSpec RTLIL::SigSpec::extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other) const { - std::set pattern_bits = pattern.to_sigbit_set(); + nodict pattern_bits = pattern.to_sigbit_nodict(); return extract(pattern_bits, other); } -RTLIL::SigSpec RTLIL::SigSpec::extract(const std::set &pattern, const RTLIL::SigSpec *other) const +RTLIL::SigSpec RTLIL::SigSpec::extract(const nodict &pattern, const RTLIL::SigSpec *other) const { if (other) cover("kernel.rtlil.sigspec.extract_other"); @@ -2917,6 +2943,18 @@ std::set RTLIL::SigSpec::to_sigbit_set() const return sigbits; } +nodict RTLIL::SigSpec::to_sigbit_nodict() const +{ + cover("kernel.rtlil.sigspec.to_sigbit_nodict"); + + pack(); + nodict sigbits; + for (auto &c : chunks_) + for (int i = 0; i < c.width; i++) + sigbits.insert(RTLIL::SigBit(c, i)); + return sigbits; +} + std::vector RTLIL::SigSpec::to_sigbit_vector() const { cover("kernel.rtlil.sigspec.to_sigbit_vector"); @@ -2941,6 +2979,22 @@ std::map RTLIL::SigSpec::to_sigbit_map(const RTLIL return new_map; } +dict RTLIL::SigSpec::to_sigbit_dict(const RTLIL::SigSpec &other) const +{ + cover("kernel.rtlil.sigspec.to_sigbit_dict"); + + unpack(); + other.unpack(); + + log_assert(width_ == other.width_); + + dict new_map; + for (int i = 0; i < width_; i++) + new_map[bits_[i]] = other.bits_[i]; + + return new_map; +} + RTLIL::SigBit RTLIL::SigSpec::to_single_sigbit() const { cover("kernel.rtlil.sigspec.to_single_sigbit"); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 99831244e..e684ba4ae 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -22,6 +22,27 @@ #ifndef RTLIL_H #define RTLIL_H +namespace std { + template<> struct hash { + size_t operator()(const Yosys::RTLIL::IdString &arg) const; + }; + template<> struct equal_to { + bool operator()(const Yosys::RTLIL::IdString &lhs, const Yosys::RTLIL::IdString &rhs) const; + }; + template<> struct hash { + size_t operator()(const Yosys::RTLIL::SigBit &arg) const; + }; + template<> struct equal_to { + bool operator()(const Yosys::RTLIL::SigBit &lhs, const Yosys::RTLIL::SigBit &rhs) const; + }; + template<> struct hash { + size_t operator()(const Yosys::RTLIL::SigSpec &arg) const; + }; + template<> struct equal_to { + bool operator()(const Yosys::RTLIL::SigSpec &lhs, const Yosys::RTLIL::SigSpec &rhs) const; + }; +} + YOSYS_NAMESPACE_BEGIN namespace RTLIL @@ -85,6 +106,24 @@ namespace RTLIL } }; + struct char_ptr_hash { + size_t operator()(const char *a) const { + size_t hash = 5381; + for (int c; (c = *a); a++) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + return hash; + } + }; + + struct char_ptr_eq { + bool operator()(const char *a, const char *b) const { + for (int i = 0; a[i] || b[i]; i++) + if (a[i] != b[i]) + return false; + return true; + } + }; + static struct destruct_guard_t { bool ok; // POD, will be initialized to zero destruct_guard_t() { ok = true; } @@ -93,7 +132,7 @@ namespace RTLIL static std::vector global_refcount_storage_; static std::vector global_id_storage_; - static std::map global_id_index_; + static dict global_id_index_; static std::vector global_free_idx_list_; static inline int get_reference(int idx) @@ -224,8 +263,8 @@ namespace RTLIL *this = IdString(); } - // The following is a helper key_compare class. Instead of for example std::set - // use std::set> if the order of cells in the + // The following is a helper key_compare class. Instead of for example nodict + // use nodict> if the order of cells in the // set has an influence on the algorithm. template struct compare_ptr_by_name { @@ -245,7 +284,7 @@ namespace RTLIL bool in(IdString rhs) { return *this == rhs; } bool in(const char *rhs) { return *this == rhs; } bool in(const std::string &rhs) { return *this == rhs; } - bool in(const std::set &rhs) { return rhs.count(*this) != 0; } + bool in(const nodict &rhs) { return rhs.count(*this) != 0; } }; static inline std::string escape_id(std::string str) { @@ -336,8 +375,8 @@ namespace RTLIL template struct ObjIterator { - typename std::map::iterator it; - std::map *list_p; + typename dict::iterator it; + dict *list_p; int *refcount_p; ObjIterator() : list_p(nullptr), refcount_p(nullptr) { @@ -401,7 +440,7 @@ namespace RTLIL template struct ObjRange { - std::map *list_p; + dict *list_p; int *refcount_p; ObjRange(decltype(list_p) list_p, int *refcount_p) : list_p(list_p), refcount_p(refcount_p) { } @@ -412,8 +451,8 @@ namespace RTLIL return list_p->size(); } - operator std::set() const { - std::set result; + operator nodict() const { + nodict result; for (auto &it : *list_p) result.insert(it.second); return result; @@ -427,7 +466,7 @@ namespace RTLIL return result; } - std::set to_set() const { return *this; } + nodict to_set() const { return *this; } std::vector to_vector() const { return *this; } }; }; @@ -457,11 +496,232 @@ struct RTLIL::Const inline int size() const { return bits.size(); } }; +struct RTLIL::SigChunk +{ + RTLIL::Wire *wire; + std::vector data; // only used if wire == NULL, LSB at index 0 + int width, offset; + + SigChunk(); + SigChunk(const RTLIL::Const &value); + SigChunk(RTLIL::Wire *wire); + SigChunk(RTLIL::Wire *wire, int offset, int width = 1); + SigChunk(const std::string &str); + SigChunk(int val, int width = 32); + SigChunk(RTLIL::State bit, int width = 1); + SigChunk(RTLIL::SigBit bit); + + RTLIL::SigChunk extract(int offset, int length) const; + + bool operator <(const RTLIL::SigChunk &other) const; + bool operator ==(const RTLIL::SigChunk &other) const; + bool operator !=(const RTLIL::SigChunk &other) const; +}; + +struct RTLIL::SigBit +{ + RTLIL::Wire *wire; + union { + RTLIL::State data; // used if wire == NULL + int offset; // used if wire != NULL + }; + + SigBit(); + SigBit(RTLIL::State bit); + SigBit(bool bit); + SigBit(RTLIL::Wire *wire); + SigBit(RTLIL::Wire *wire, int offset); + SigBit(const RTLIL::SigChunk &chunk); + SigBit(const RTLIL::SigChunk &chunk, int index); + SigBit(const RTLIL::SigSpec &sig); + + bool operator <(const RTLIL::SigBit &other) const; + bool operator ==(const RTLIL::SigBit &other) const; + bool operator !=(const RTLIL::SigBit &other) const; +}; + +struct RTLIL::SigSpecIterator : public std::iterator +{ + RTLIL::SigSpec *sig_p; + int index; + + inline RTLIL::SigBit &operator*() const; + inline bool operator!=(const RTLIL::SigSpecIterator &other) const { return index != other.index; } + inline bool operator==(const RTLIL::SigSpecIterator &other) const { return index == other.index; } + inline void operator++() { index++; } +}; + +struct RTLIL::SigSpecConstIterator : public std::iterator +{ + const RTLIL::SigSpec *sig_p; + int index; + + inline const RTLIL::SigBit &operator*() const; + inline bool operator!=(const RTLIL::SigSpecConstIterator &other) const { return index != other.index; } + inline bool operator==(const RTLIL::SigSpecIterator &other) const { return index == other.index; } + inline void operator++() { index++; } +}; + +struct RTLIL::SigSpec +{ +private: + int width_; + unsigned long hash_; + std::vector chunks_; // LSB at index 0 + std::vector bits_; // LSB at index 0 + + void pack() const; + void unpack() const; + void hash() const; + + inline bool packed() const { + return bits_.empty(); + } + + inline void inline_unpack() const { + if (!chunks_.empty()) + unpack(); + } + +public: + SigSpec(); + SigSpec(const RTLIL::SigSpec &other); + SigSpec(std::initializer_list parts); + const RTLIL::SigSpec &operator=(const RTLIL::SigSpec &other); + + SigSpec(const RTLIL::Const &value); + SigSpec(const RTLIL::SigChunk &chunk); + SigSpec(RTLIL::Wire *wire); + SigSpec(RTLIL::Wire *wire, int offset, int width = 1); + SigSpec(const std::string &str); + SigSpec(int val, int width = 32); + SigSpec(RTLIL::State bit, int width = 1); + SigSpec(RTLIL::SigBit bit, int width = 1); + SigSpec(std::vector chunks); + SigSpec(std::vector bits); + SigSpec(nodict bits); + SigSpec(std::set bits); + SigSpec(bool bit); + + SigSpec(RTLIL::SigSpec &&other) { + width_ = other.width_; + hash_ = other.hash_; + chunks_ = std::move(other.chunks_); + bits_ = std::move(other.bits_); + } + + const RTLIL::SigSpec &operator=(RTLIL::SigSpec &&other) { + width_ = other.width_; + hash_ = other.hash_; + chunks_ = std::move(other.chunks_); + bits_ = std::move(other.bits_); + return *this; + } + + size_t get_hash() const { + if (!hash_) hash(); + return hash_; + } + + inline const std::vector &chunks() const { pack(); return chunks_; } + inline const std::vector &bits() const { inline_unpack(); return bits_; } + + inline int size() const { return width_; } + inline bool empty() const { return width_ == 0; } + + inline RTLIL::SigBit &operator[](int index) { inline_unpack(); return bits_.at(index); } + inline const RTLIL::SigBit &operator[](int index) const { inline_unpack(); return bits_.at(index); } + + inline RTLIL::SigSpecIterator begin() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = 0; return it; } + inline RTLIL::SigSpecIterator end() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = width_; return it; } + + inline RTLIL::SigSpecConstIterator begin() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = 0; return it; } + inline RTLIL::SigSpecConstIterator end() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = width_; return it; } + + void sort(); + void sort_and_unify(); + + void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with); + void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with, RTLIL::SigSpec *other) const; + + void replace(const dict &rules); + void replace(const dict &rules, RTLIL::SigSpec *other) const; + + void replace(const std::map &rules); + void replace(const std::map &rules, RTLIL::SigSpec *other) const; + + void replace(int offset, const RTLIL::SigSpec &with); + + void remove(const RTLIL::SigSpec &pattern); + void remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) const; + void remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other); + + void remove(const nodict &pattern); + void remove(const nodict &pattern, RTLIL::SigSpec *other) const; + void remove2(const nodict &pattern, RTLIL::SigSpec *other); + + void remove(int offset, int length = 1); + void remove_const(); + + RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const; + RTLIL::SigSpec extract(const nodict &pattern, const RTLIL::SigSpec *other = NULL) const; + RTLIL::SigSpec extract(int offset, int length = 1) const; + + void append(const RTLIL::SigSpec &signal); + void append_bit(const RTLIL::SigBit &bit); + + void extend_xx(int width, bool is_signed = false); + void extend_u0(int width, bool is_signed = false); + + RTLIL::SigSpec repeat(int num) const; + + bool operator <(const RTLIL::SigSpec &other) const; + bool operator ==(const RTLIL::SigSpec &other) const; + inline bool operator !=(const RTLIL::SigSpec &other) const { return !(*this == other); } + + bool is_wire() const; + bool is_chunk() const; + + bool is_fully_const() const; + bool is_fully_def() const; + bool is_fully_undef() const; + bool has_marked_bits() const; + + bool as_bool() const; + int as_int(bool is_signed = false) const; + std::string as_string() const; + RTLIL::Const as_const() const; + RTLIL::Wire *as_wire() const; + RTLIL::SigChunk as_chunk() const; + + bool match(std::string pattern) const; + + std::set to_sigbit_set() const; + nodict to_sigbit_nodict() const; + std::vector to_sigbit_vector() const; + std::map to_sigbit_map(const RTLIL::SigSpec &other) const; + dict to_sigbit_dict(const RTLIL::SigSpec &other) const; + RTLIL::SigBit to_single_sigbit() const; + + static bool parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str); + static bool parse_sel(RTLIL::SigSpec &sig, RTLIL::Design *design, RTLIL::Module *module, std::string str); + static bool parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str); + + operator std::vector() const { return chunks(); } + operator std::vector() const { return bits(); } + +#ifndef NDEBUG + void check() const; +#else + void check() const { } +#endif +}; + struct RTLIL::Selection { bool full_selection; - std::set selected_modules; - std::map> selected_members; + nodict selected_modules; + dict> selected_members; Selection(bool full = true) : full_selection(full) { } @@ -500,14 +760,14 @@ struct RTLIL::Monitor struct RTLIL::Design { - std::set monitors; - std::map scratchpad; + nodict monitors; + dict scratchpad; int refcount_modules_; - std::map modules_; + dict modules_; std::vector selection_stack; - std::map selection_vars; + dict selection_vars; std::string selected_active_module; Design(); @@ -569,7 +829,7 @@ struct RTLIL::Design }; #define RTLIL_ATTRIBUTE_MEMBERS \ - std::map attributes; \ + dict attributes; \ void set_bool_attribute(RTLIL::IdString id) { \ attributes[id] = RTLIL::Const(1); \ } \ @@ -587,24 +847,24 @@ protected: public: RTLIL::Design *design; - std::set monitors; + nodict monitors; int refcount_wires_; int refcount_cells_; - std::map wires_; - std::map cells_; + dict wires_; + dict cells_; std::vector connections_; RTLIL::IdString name; - std::set avail_parameters; - std::map memories; - std::map processes; + nodict avail_parameters; + dict memories; + dict processes; RTLIL_ATTRIBUTE_MEMBERS Module(); virtual ~Module(); - virtual RTLIL::IdString derive(RTLIL::Design *design, std::map parameters); + virtual RTLIL::IdString derive(RTLIL::Design *design, dict parameters); virtual size_t count_id(RTLIL::IdString id); virtual void check(); virtual void optimize(); @@ -641,7 +901,7 @@ public: RTLIL::ObjRange cells() { return RTLIL::ObjRange(&cells_, &refcount_cells_); } // Removing wires is expensive. If you have to remove wires, remove them all at once. - void remove(const std::set &wires); + void remove(const nodict &wires); void remove(RTLIL::Cell *cell); void rename(RTLIL::Wire *wire, RTLIL::IdString new_name); @@ -852,8 +1112,8 @@ public: RTLIL::Module *module; RTLIL::IdString name; RTLIL::IdString type; - std::map connections_; - std::map parameters; + dict connections_; + dict parameters; RTLIL_ATTRIBUTE_MEMBERS // access cell ports @@ -861,7 +1121,7 @@ public: void unsetPort(RTLIL::IdString portname); void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal); const RTLIL::SigSpec &getPort(RTLIL::IdString portname) const; - const std::map &connections() const; + const dict &connections() const; // access cell parameters bool hasParam(RTLIL::IdString paramname) const; @@ -880,241 +1140,6 @@ public: template void rewrite_sigspecs(T functor); }; -struct RTLIL::SigChunk -{ - RTLIL::Wire *wire; - std::vector data; // only used if wire == NULL, LSB at index 0 - int width, offset; - - SigChunk(); - SigChunk(const RTLIL::Const &value); - SigChunk(RTLIL::Wire *wire); - SigChunk(RTLIL::Wire *wire, int offset, int width = 1); - SigChunk(const std::string &str); - SigChunk(int val, int width = 32); - SigChunk(RTLIL::State bit, int width = 1); - SigChunk(RTLIL::SigBit bit); - - RTLIL::SigChunk extract(int offset, int length) const; - - bool operator <(const RTLIL::SigChunk &other) const; - bool operator ==(const RTLIL::SigChunk &other) const; - bool operator !=(const RTLIL::SigChunk &other) const; -}; - -struct RTLIL::SigBit -{ - RTLIL::Wire *wire; - union { - RTLIL::State data; // used if wire == NULL - int offset; // used if wire != NULL - }; - - SigBit() : wire(NULL), data(RTLIL::State::S0) { } - SigBit(RTLIL::State bit) : wire(NULL), data(bit) { } - SigBit(bool bit) : wire(NULL), data(bit ? RTLIL::S1 : RTLIL::S0) { } - SigBit(RTLIL::Wire *wire) : wire(wire), offset(0) { log_assert(wire && wire->width == 1); } - SigBit(RTLIL::Wire *wire, int offset) : wire(wire), offset(offset) { log_assert(wire != nullptr); } - SigBit(const RTLIL::SigChunk &chunk) : wire(chunk.wire) { log_assert(chunk.width == 1); if (wire) offset = chunk.offset; else data = chunk.data[0]; } - SigBit(const RTLIL::SigChunk &chunk, int index) : wire(chunk.wire) { if (wire) offset = chunk.offset + index; else data = chunk.data[index]; } - SigBit(const RTLIL::SigSpec &sig); - - bool operator <(const RTLIL::SigBit &other) const { - if (wire == other.wire) - return wire ? (offset < other.offset) : (data < other.data); - if (wire != nullptr && other.wire != nullptr) - return wire->name < other.wire->name; - return wire < other.wire; - } - - bool operator ==(const RTLIL::SigBit &other) const { - return (wire == other.wire) && (wire ? (offset == other.offset) : (data == other.data)); - } - - bool operator !=(const RTLIL::SigBit &other) const { - return (wire != other.wire) || (wire ? (offset != other.offset) : (data != other.data)); - } -}; - -struct RTLIL::SigSpecIterator : public std::iterator -{ - RTLIL::SigSpec *sig_p; - int index; - - inline RTLIL::SigBit &operator*() const; - inline bool operator!=(const RTLIL::SigSpecIterator &other) const { return index != other.index; } - inline bool operator==(const RTLIL::SigSpecIterator &other) const { return index == other.index; } - inline void operator++() { index++; } -}; - -struct RTLIL::SigSpecConstIterator : public std::iterator -{ - const RTLIL::SigSpec *sig_p; - int index; - - inline const RTLIL::SigBit &operator*() const; - inline bool operator!=(const RTLIL::SigSpecConstIterator &other) const { return index != other.index; } - inline bool operator==(const RTLIL::SigSpecIterator &other) const { return index == other.index; } - inline void operator++() { index++; } -}; - -struct RTLIL::SigSpec -{ -private: - int width_; - unsigned long hash_; - std::vector chunks_; // LSB at index 0 - std::vector bits_; // LSB at index 0 - - void pack() const; - void unpack() const; - void hash() const; - - inline bool packed() const { - return bits_.empty(); - } - - inline void inline_unpack() const { - if (!chunks_.empty()) - unpack(); - } - -public: - SigSpec(); - SigSpec(const RTLIL::SigSpec &other); - SigSpec(std::initializer_list parts); - const RTLIL::SigSpec &operator=(const RTLIL::SigSpec &other); - - SigSpec(const RTLIL::Const &value); - SigSpec(const RTLIL::SigChunk &chunk); - SigSpec(RTLIL::Wire *wire); - SigSpec(RTLIL::Wire *wire, int offset, int width = 1); - SigSpec(const std::string &str); - SigSpec(int val, int width = 32); - SigSpec(RTLIL::State bit, int width = 1); - SigSpec(RTLIL::SigBit bit, int width = 1); - SigSpec(std::vector chunks); - SigSpec(std::vector bits); - SigSpec(std::set bits); - SigSpec(bool bit); - - SigSpec(RTLIL::SigSpec &&other) { - width_ = other.width_; - hash_ = other.hash_; - chunks_ = std::move(other.chunks_); - bits_ = std::move(other.bits_); - } - - const RTLIL::SigSpec &operator=(RTLIL::SigSpec &&other) { - width_ = other.width_; - hash_ = other.hash_; - chunks_ = std::move(other.chunks_); - bits_ = std::move(other.bits_); - return *this; - } - - inline const std::vector &chunks() const { pack(); return chunks_; } - inline const std::vector &bits() const { inline_unpack(); return bits_; } - - inline int size() const { return width_; } - inline bool empty() const { return width_ == 0; } - - inline RTLIL::SigBit &operator[](int index) { inline_unpack(); return bits_.at(index); } - inline const RTLIL::SigBit &operator[](int index) const { inline_unpack(); return bits_.at(index); } - - inline RTLIL::SigSpecIterator begin() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = 0; return it; } - inline RTLIL::SigSpecIterator end() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = width_; return it; } - - inline RTLIL::SigSpecConstIterator begin() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = 0; return it; } - inline RTLIL::SigSpecConstIterator end() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = width_; return it; } - - void sort(); - void sort_and_unify(); - - void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with); - void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with, RTLIL::SigSpec *other) const; - - void replace(const std::map &rules); - void replace(const std::map &rules, RTLIL::SigSpec *other) const; - - void replace(int offset, const RTLIL::SigSpec &with); - - void remove(const RTLIL::SigSpec &pattern); - void remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) const; - void remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other); - - void remove(const std::set &pattern); - void remove(const std::set &pattern, RTLIL::SigSpec *other) const; - void remove2(const std::set &pattern, RTLIL::SigSpec *other); - - void remove(int offset, int length = 1); - void remove_const(); - - RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const; - RTLIL::SigSpec extract(const std::set &pattern, const RTLIL::SigSpec *other = NULL) const; - RTLIL::SigSpec extract(int offset, int length = 1) const; - - void append(const RTLIL::SigSpec &signal); - void append_bit(const RTLIL::SigBit &bit); - - void extend_xx(int width, bool is_signed = false); - void extend_u0(int width, bool is_signed = false); - - RTLIL::SigSpec repeat(int num) const; - - bool operator <(const RTLIL::SigSpec &other) const; - bool operator ==(const RTLIL::SigSpec &other) const; - inline bool operator !=(const RTLIL::SigSpec &other) const { return !(*this == other); } - - bool is_wire() const; - bool is_chunk() const; - - bool is_fully_const() const; - bool is_fully_def() const; - bool is_fully_undef() const; - bool has_marked_bits() const; - - bool as_bool() const; - int as_int(bool is_signed = false) const; - std::string as_string() const; - RTLIL::Const as_const() const; - RTLIL::Wire *as_wire() const; - RTLIL::SigChunk as_chunk() const; - - bool match(std::string pattern) const; - - std::set to_sigbit_set() const; - std::vector to_sigbit_vector() const; - std::map to_sigbit_map(const RTLIL::SigSpec &other) const; - RTLIL::SigBit to_single_sigbit() const; - - static bool parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str); - static bool parse_sel(RTLIL::SigSpec &sig, RTLIL::Design *design, RTLIL::Module *module, std::string str); - static bool parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str); - - operator std::vector() const { return chunks(); } - operator std::vector() const { return bits(); } - -#ifndef NDEBUG - void check() const; -#else - inline void check() const { } -#endif -}; - -inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const { - return (*sig_p)[index]; -} - -inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() const { - return (*sig_p)[index]; -} - -inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) { - log_assert(sig.size() == 1 && sig.chunks().size() == 1); - *this = SigBit(sig.chunks().front()); -} - struct RTLIL::CaseRule { std::vector compare; @@ -1163,6 +1188,44 @@ struct RTLIL::Process RTLIL::Process *clone() const; }; + +inline RTLIL::SigBit::SigBit() : wire(NULL), data(RTLIL::State::S0) { } +inline RTLIL::SigBit::SigBit(RTLIL::State bit) : wire(NULL), data(bit) { } +inline RTLIL::SigBit::SigBit(bool bit) : wire(NULL), data(bit ? RTLIL::S1 : RTLIL::S0) { } +inline RTLIL::SigBit::SigBit(RTLIL::Wire *wire) : wire(wire), offset(0) { log_assert(wire && wire->width == 1); } +inline RTLIL::SigBit::SigBit(RTLIL::Wire *wire, int offset) : wire(wire), offset(offset) { log_assert(wire != nullptr); } +inline RTLIL::SigBit::SigBit(const RTLIL::SigChunk &chunk) : wire(chunk.wire) { log_assert(chunk.width == 1); if (wire) offset = chunk.offset; else data = chunk.data[0]; } +inline RTLIL::SigBit::SigBit(const RTLIL::SigChunk &chunk, int index) : wire(chunk.wire) { if (wire) offset = chunk.offset + index; else data = chunk.data[index]; } + +inline bool RTLIL::SigBit::operator<(const RTLIL::SigBit &other) const { + if (wire == other.wire) + return wire ? (offset < other.offset) : (data < other.data); + if (wire != nullptr && other.wire != nullptr) + return wire->name < other.wire->name; + return wire < other.wire; +} + +inline bool RTLIL::SigBit::operator==(const RTLIL::SigBit &other) const { + return (wire == other.wire) && (wire ? (offset == other.offset) : (data == other.data)); +} + +inline bool RTLIL::SigBit::operator!=(const RTLIL::SigBit &other) const { + return (wire != other.wire) || (wire ? (offset != other.offset) : (data != other.data)); +} + +inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const { + return (*sig_p)[index]; +} + +inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() const { + return (*sig_p)[index]; +} + +inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) { + log_assert(sig.size() == 1 && sig.chunks().size() == 1); + *this = SigBit(sig.chunks().front()); +} + template void RTLIL::Module::rewrite_sigspecs(T functor) { @@ -1222,4 +1285,35 @@ void RTLIL::Process::rewrite_sigspecs(T functor) YOSYS_NAMESPACE_END +inline size_t std::hash::operator()(const Yosys::RTLIL::IdString &arg) const { + return arg.index_; +} + +inline bool std::equal_to::operator()(const Yosys::RTLIL::IdString &lhs, const Yosys::RTLIL::IdString &rhs) const { + return lhs.index_ == rhs.index_; +} + +inline size_t std::hash::operator()(const Yosys::RTLIL::SigBit &arg) const { + if (arg.wire) { + size_t hash = arg.wire->name.index_; + hash = ((hash << 5) + hash) + arg.offset; + return hash; + } + return arg.data; +} + +inline bool std::equal_to::operator()(const Yosys::RTLIL::SigBit &lhs, const Yosys::RTLIL::SigBit &rhs) const { + if (lhs.wire || rhs.wire) + return lhs.wire == rhs.wire && lhs.offset == rhs.offset; + return lhs.data == rhs.data; +} + +inline size_t std::hash::operator()(const Yosys::RTLIL::SigSpec &arg) const { + return arg.get_hash(); +} + +inline bool std::equal_to::operator()(const Yosys::RTLIL::SigSpec &lhs, const Yosys::RTLIL::SigSpec &rhs) const { + return lhs == rhs; +} + #endif diff --git a/kernel/yosys.h b/kernel/yosys.h index b64739ad4..5a6945c8f 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -45,6 +45,8 @@ #include #include #include +#include +#include #include #include @@ -122,8 +124,18 @@ YOSYS_NAMESPACE_BEGIN +template , class KeyEqual = std::equal_to> +using dict = std::unordered_map; + +template , class KeyEqual = std::equal_to> +using nodict = std::unordered_set; + +template +using vector = std::vector; + namespace RTLIL { struct IdString; + struct SigBit; struct SigSpec; struct Wire; struct Cell; diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc index 8c3391e52..d7edcfbfc 100644 --- a/passes/cmds/delete.cc +++ b/passes/cmds/delete.cc @@ -91,10 +91,10 @@ struct DeletePass : public Pass { continue; } - std::set delete_wires; - std::set delete_cells; - std::set delete_procs; - std::set delete_mems; + nodict delete_wires; + nodict delete_cells; + nodict delete_procs; + nodict delete_mems; for (auto &it : module->wires_) if (design->selected(module, it.second)) diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc index b2e10e557..8f24af278 100644 --- a/passes/cmds/rename.cc +++ b/passes/cmds/rename.cc @@ -118,7 +118,7 @@ struct RenamePass : public Pass { if (!design->selected(module)) continue; - std::map new_wires; + dict new_wires; for (auto &it : module->wires_) { if (it.first[0] == '$' && design->selected(module, it.second)) do it.second->name = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str()); @@ -128,7 +128,7 @@ struct RenamePass : public Pass { module->wires_.swap(new_wires); module->fixup_ports(); - std::map new_cells; + dict new_cells; for (auto &it : module->cells_) { if (it.first[0] == '$' && design->selected(module, it.second)) do it.second->name = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str()); @@ -149,7 +149,7 @@ struct RenamePass : public Pass { if (!design->selected(module)) continue; - std::map new_wires; + dict new_wires; for (auto &it : module->wires_) { if (design->selected(module, it.second)) if (it.first[0] == '\\' && it.second->port_id == 0) @@ -159,7 +159,7 @@ struct RenamePass : public Pass { module->wires_.swap(new_wires); module->fixup_ports(); - std::map new_cells; + dict new_cells; for (auto &it : module->cells_) { if (design->selected(module, it.second)) if (it.first[0] == '\\') diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 7f841673f..91368f572 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -101,7 +101,7 @@ static bool match_attr_val(const RTLIL::Const &value, std::string pattern, char log_abort(); } -static bool match_attr(const std::map &attributes, std::string name_pat, std::string value_pat, char match_op) +static bool match_attr(const dict &attributes, std::string name_pat, std::string value_pat, char match_op) { if (name_pat.find('*') != std::string::npos || name_pat.find('?') != std::string::npos || name_pat.find('[') != std::string::npos) { for (auto &it : attributes) { @@ -119,7 +119,7 @@ static bool match_attr(const std::map &attributes return false; } -static bool match_attr(const std::map &attributes, std::string match_expr) +static bool match_attr(const dict &attributes, std::string match_expr) { size_t pos = match_expr.find_first_of(""); diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc index 39c75c54e..9a6d8a038 100644 --- a/passes/cmds/setattr.cc +++ b/passes/cmds/setattr.cc @@ -50,7 +50,7 @@ struct setunset_t } }; -static void do_setunset(std::map &attrs, std::vector &list) +static void do_setunset(dict &attrs, std::vector &list) { for (auto &item : list) if (item.unset) diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc index a6c9fe883..6c24a8e5f 100644 --- a/passes/cmds/splitnets.cc +++ b/passes/cmds/splitnets.cc @@ -176,7 +176,7 @@ struct SplitnetsPass : public Pass { module->rewrite_sigspecs(worker); - std::set delete_wires; + nodict delete_wires; for (auto &it : worker.splitmap) delete_wires.insert(it.first); module->remove(delete_wires); diff --git a/passes/fsm/fsm_export.cc b/passes/fsm/fsm_export.cc index 668fe8d1d..ad9270334 100644 --- a/passes/fsm/fsm_export.cc +++ b/passes/fsm/fsm_export.cc @@ -50,7 +50,7 @@ std::string kiss_convert_signal(const RTLIL::SigSpec &sig) { * @param cell pointer to the FSM cell which should be exported. */ void write_kiss2(struct RTLIL::Module *module, struct RTLIL::Cell *cell, std::string filename, bool origenc) { - std::map::iterator attr_it; + dict::iterator attr_it; FsmData fsm_data; FsmData::transition_t tr; std::ofstream kiss_file; @@ -145,7 +145,7 @@ struct FsmExportPass : public Pass { } virtual void execute(std::vector args, RTLIL::Design *design) { - std::map::iterator attr_it; + dict::iterator attr_it; std::string arg; bool flag_noauto = false; std::string filename; diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index e95947a92..66d660324 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -462,7 +462,7 @@ struct HierarchyPass : public Pass { log_cmd_error("Option -top requires an additional argument!\n"); top_mod = design->modules_.count(RTLIL::escape_id(args[argidx])) ? design->modules_.at(RTLIL::escape_id(args[argidx])) : NULL; if (top_mod == NULL && design->modules_.count("$abstract" + RTLIL::escape_id(args[argidx]))) { - std::map empty_parameters; + dict empty_parameters; design->modules_.at("$abstract" + RTLIL::escape_id(args[argidx]))->derive(design, empty_parameters); top_mod = design->modules_.count(RTLIL::escape_id(args[argidx])) ? design->modules_.at(RTLIL::escape_id(args[argidx])) : NULL; } @@ -560,7 +560,7 @@ struct HierarchyPass : public Pass { RTLIL::Cell *cell = work.second; log("Mapping positional arguments of cell %s.%s (%s).\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); - std::map new_connections; + dict new_connections; for (auto &conn : cell->connections()) if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') { int id = atoi(conn.first.c_str()+1); diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 8a20898cf..01acb5c04 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -262,7 +262,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } - std::set del_wires; + nodict del_wires; int del_wires_count = 0; for (auto wire : maybe_del_wires) diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc index 5bac76cf6..7f800bde9 100644 --- a/passes/opt/opt_const.cc +++ b/passes/opt/opt_const.cc @@ -196,11 +196,11 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons ct_combinational.setup_stdcells(); SigMap assign_map(module); - std::map invert_map; + dict invert_map; TopoSort> cells; - std::map> cell_to_inbit; - std::map> outbit_to_cell; + dict> cell_to_inbit; + dict> outbit_to_cell; for (auto cell : module->cells()) if (design->selected(module, cell) && cell->type[0] == '$') { diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index f8bc02205..c581b749e 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -41,7 +41,7 @@ struct OptShareWorker CellTypes ct; int total_count; #ifdef USE_CELL_HASH_CACHE - std::map cell_hash_cache; + dict cell_hash_cache; #endif #ifdef USE_CELL_HASH_CACHE @@ -67,8 +67,8 @@ struct OptShareWorker for (auto &it : cell->parameters) hash_string += "P " + it.first.str() + "=" + it.second.as_string() + "\n"; - const std::map *conn = &cell->connections(); - std::map alt_conn; + const dict *conn = &cell->connections(); + dict alt_conn; if (cell->type == "$and" || cell->type == "$or" || cell->type == "$xor" || cell->type == "$xnor" || cell->type == "$add" || cell->type == "$mul" || cell->type == "$logic_and" || cell->type == "$logic_or" || cell->type == "$_AND_" || cell->type == "$_OR_" || cell->type == "$_XOR_") { @@ -127,12 +127,14 @@ struct OptShareWorker #endif if (cell1->parameters != cell2->parameters) { - lt = cell1->parameters < cell2->parameters; + std::map p1(cell1->parameters.begin(), cell1->parameters.end()); + std::map p2(cell2->parameters.begin(), cell2->parameters.end()); + lt = p1 < p2; return true; } - std::map conn1 = cell1->connections(); - std::map conn2 = cell2->connections(); + dict conn1 = cell1->connections(); + dict conn2 = cell2->connections(); for (auto &it : conn1) { if (ct.cell_output(cell1->type, it.first)) @@ -171,7 +173,9 @@ struct OptShareWorker } if (conn1 != conn2) { - lt = conn1 < conn2; + std::map c1(conn1.begin(), conn1.end()); + std::map c2(conn2.begin(), conn2.end()); + lt = c1 < c2; return true; } diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 8f59a041e..e8a38d212 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -28,11 +28,11 @@ PRIVATE_NAMESPACE_BEGIN struct WreduceConfig { - std::set supported_cell_types; + nodict supported_cell_types; WreduceConfig() { - supported_cell_types = std::set({ + supported_cell_types = nodict({ "$not", "$pos", "$neg", "$and", "$or", "$xor", "$xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc index 994ef8f2a..ff99040e1 100644 --- a/passes/techmap/extract.cc +++ b/passes/techmap/extract.cc @@ -42,7 +42,7 @@ public: { } - bool compareAttributes(const std::set &attr, const std::map &needleAttr, const std::map &haystackAttr) + bool compareAttributes(const std::set &attr, const dict &needleAttr, const dict &haystackAttr) { for (auto &it : attr) { size_t nc = needleAttr.count(it), hc = haystackAttr.count(it); @@ -123,7 +123,7 @@ public: { RTLIL::Wire *lastNeedleWire = NULL; RTLIL::Wire *lastHaystackWire = NULL; - std::map emptyAttr; + dict emptyAttr; for (auto &conn : needleCell->connections()) { diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 04d345d31..94dd4d42c 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -341,7 +341,7 @@ struct TechmapWorker { RTLIL::IdString derived_name = tpl_name; RTLIL::Module *tpl = map->modules_[tpl_name]; - std::map parameters = cell->parameters; + std::map parameters(cell->parameters.begin(), cell->parameters.end()); if (tpl->get_bool_attribute("\\blackbox")) continue; @@ -529,7 +529,7 @@ struct TechmapWorker tpl = techmap_cache[key]; } else { if (cell->parameters.size() != 0) { - derived_name = tpl->derive(map, parameters); + derived_name = tpl->derive(map, dict(parameters.begin(), parameters.end())); tpl = map->module(derived_name); log_continue = true; } @@ -975,7 +975,7 @@ struct TechmapPass : public Pass { Frontend::frontend_call(map, &f, fn, (fn.size() > 3 && fn.substr(fn.size()-3) == ".il") ? "ilang" : verilog_frontend); } - std::map modules_new; + dict modules_new; for (auto &it : map->modules_) { if (it.first.substr(0, 2) == "\\$") it.second->name = it.first.substr(1); @@ -1072,7 +1072,7 @@ struct FlattenPass : public Pass { log("No more expansions possible.\n"); if (top_mod != NULL) { - std::map new_modules; + dict new_modules; for (auto mod : design->modules()) if (mod == top_mod || mod->get_bool_attribute("\\blackbox")) { new_modules[mod->name] = mod; From 35f611e2f6b38b18fc50fadbb07df1d1bc462583 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 26 Dec 2014 10:54:23 +0100 Subject: [PATCH 181/492] Added "yosys -d" command line option --- kernel/driver.cc | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index 7f466839c..6ba0c1134 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -80,6 +80,7 @@ int main(int argc, char **argv) bool print_banner = true; bool print_stats = true; bool call_abort = false; + bool timing_details = false; #ifdef YOSYS_ENABLE_READLINE int history_offset = 0; @@ -92,7 +93,7 @@ int main(int argc, char **argv) #endif int opt; - while ((opt = getopt(argc, argv, "AQTVSm:f:Hh:b:o:p:l:qv:ts:c:")) != -1) + while ((opt = getopt(argc, argv, "AQTVSm:f:Hh:b:o:p:l:qv:tds:c:")) != -1) { switch (opt) { @@ -152,6 +153,9 @@ int main(int argc, char **argv) case 't': log_time = true; break; + case 'd': + timing_details = true; + break; case 's': scriptfile = optarg; scriptfile_tcl = false; @@ -181,6 +185,9 @@ int main(int argc, char **argv) fprintf(stderr, " -t\n"); fprintf(stderr, " annotate all log messages with a time stamp\n"); fprintf(stderr, "\n"); + fprintf(stderr, " -d\n"); + fprintf(stderr, " print more detailed timing stats at exit\n"); + fprintf(stderr, "\n"); fprintf(stderr, " -l logfile\n"); fprintf(stderr, " write log messages to the specified file\n"); fprintf(stderr, "\n"); @@ -325,17 +332,28 @@ int main(int argc, char **argv) timedat.insert(make_tuple(it.second->runtime_ns + 1, it.second->call_counter, it.first)); } - int out_count = 0; - log("Time spent:"); - for (auto it = timedat.rbegin(); it != timedat.rend() && out_count < 4; it++, out_count++) { - if (out_count >= 2 && (std::get<0>(*it) < 1000000000 || int(100*std::get<0>(*it) / total_ns) < 20)) { - log(", ..."); - break; + if (timing_details) + { + log("Time spent:\n"); + for (auto it = timedat.rbegin(); it != timedat.rend(); it++) { + log("%5d%% %5d calls %8.3f sec %s\n", int(100*std::get<0>(*it) / total_ns), + std::get<1>(*it), std::get<0>(*it) / 1000000000.0, std::get<2>(*it).c_str()); } - log("%s %d%% %dx %s (%d sec)", out_count ? "," : "", int(100*std::get<0>(*it) / total_ns), - std::get<1>(*it), std::get<2>(*it).c_str(), int(std::get<0>(*it) / 1000000000)); } - log("%s\n", out_count ? "" : " no commands executed"); + else + { + int out_count = 0; + log("Time spent:"); + for (auto it = timedat.rbegin(); it != timedat.rend() && out_count < 4; it++, out_count++) { + if (out_count >= 2 && (std::get<0>(*it) < 1000000000 || int(100*std::get<0>(*it) / total_ns) < 20)) { + log(", ..."); + break; + } + log("%s %d%% %dx %s (%d sec)", out_count ? "," : "", int(100*std::get<0>(*it) / total_ns), + std::get<1>(*it), std::get<2>(*it).c_str(), int(std::get<0>(*it) / 1000000000)); + } + log("%s\n", out_count ? "" : " no commands executed"); + } } #ifdef YOSYS_ENABLE_COVER From e0c0011863c891e0c168eb2fabecf88b2f0a45b7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 26 Dec 2014 11:05:23 +0100 Subject: [PATCH 182/492] Temporary gcc 4.6 build hotfix for Yosys::dict and Yosys::nodict --- kernel/yosys.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/kernel/yosys.h b/kernel/yosys.h index 5a6945c8f..e2daabfae 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -124,14 +124,9 @@ YOSYS_NAMESPACE_BEGIN -template , class KeyEqual = std::equal_to> -using dict = std::unordered_map; - -template , class KeyEqual = std::equal_to> -using nodict = std::unordered_set; - -template -using vector = std::vector; +#define dict std::unordered_map +#define nodict std::unordered_set +using std::vector; namespace RTLIL { struct IdString; From e52d1f9b9a7f71634d4e8e8228060f792fa20dec Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 26 Dec 2014 19:28:52 +0100 Subject: [PATCH 183/492] Added new_dict (hashmap.h) and re-enabled code coverage counters --- Makefile | 2 +- kernel/hashmap.h | 238 +++++++++++++++++++++++++++++++++++++++++++++++ kernel/log.cc | 6 +- kernel/log.h | 4 +- kernel/rtlil.cc | 2 +- kernel/yosys.h | 1 + 6 files changed, 246 insertions(+), 7 deletions(-) create mode 100644 kernel/hashmap.h diff --git a/Makefile b/Makefile index 8e3022ccd..73514e521 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ ENABLE_ABC := 1 ENABLE_PLUGINS := 1 ENABLE_READLINE := 1 ENABLE_VERIFIC := 0 -ENABLE_COVER := 0 +ENABLE_COVER := 1 # other configuration flags ENABLE_GPROF := 0 diff --git a/kernel/hashmap.h b/kernel/hashmap.h new file mode 100644 index 000000000..bd4fc4d22 --- /dev/null +++ b/kernel/hashmap.h @@ -0,0 +1,238 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef YOSYS_HASHMAP_H + +#include +#include + +inline unsigned int mkhash(unsigned int a, unsigned int b) { + return ((a << 5) + a) ^ b; +} + +template struct hash_ops { + bool cmp(const T &a, const T &b) { + return a == b; + } + unsigned int hash(const T &a) { + return a.hash(); + } +}; + +template<> struct hash_ops { + bool cmp(int a, int b) { + return a == b; + } + unsigned int hash(int a) { + return a; + } +}; + +template<> struct hash_ops { + bool cmp(const std::string &a, const std::string &b) { + return a == b; + } + unsigned int hash(const std::string &a) { + unsigned int v = 0; + for (auto c : a) + v = mkhash(v, c); + return v; + } +}; + +template> +class new_dict +{ + struct entry_t + { + int link; + std::pair udata; + entry_t() : link(-1) { } + + bool is_free() const { return link < 0; } + int get_next() const { return (link > 0 ? link : -link) - 2; } + bool get_last() const { return get_next() == -1; } + void set_next_used(int next) { link = next + 2; } + void set_next_free(int next) { link = -(next + 2); } + }; + + std::vector hashtable; + std::vector entries; + int free_list, counter; + OPS ops; + + void init() + { + counter = 0; + entries.resize(61); + rehash(); + } + + int mkhash(const K &key) + { + return ops.hash(key) % int(hashtable.size()); + } + +public: + void rehash() + { + free_list = -1; + + hashtable.resize(entries.size()); + for (auto &h : hashtable) + h = -1; + + for (int i = 0; i < int(entries.size()); i++) + if (entries[i].is_free()) { + entries[i].set_next_free(free_list); + free_list = i; + } else { + int hash = mkhash(entries[i].udata.first); + entries[i].set_next_used(hashtable[hash]); + hashtable[hash] = i; + } + } + + void do_erase(const K &key, int hash) + { + int last_index = -1; + int index = hashtable[hash]; + while (1) { + if (index < 0) + return; + if (ops.cmp(entries[index].udata.first, key)) { + if (last_index < 0) + hashtable[hash] = entries[index].get_next(); + else + entries[last_index].set_next_used(entries[index].get_next()); + entries[index].udata = std::pair(); + entries[index].set_next_free(free_list); + free_list = index; + counter--; + return; + } + last_index = index; + index = entries[index].get_next(); + } + } + + int lookup_index(const K &key, int hash) + { + int index = hashtable[hash]; + while (1) { + if (index < 0) + return -1; + if (ops.cmp(entries[index].udata.first, key)) + return index; + index = entries[index].get_next(); + } + } + + int insert_at(const std::pair &value, int hash) + { + if (free_list < 0) + { + int i = entries.size(); + entries.resize(2*entries.size()); + entries[i].udata = value; + entries[i].set_next_used(0); + counter++; + rehash(); + return i; + } + + int i = free_list; + free_list = entries[i].get_next(); + entries[i].udata = value; + entries[i].set_next_used(hashtable[hash]); + hashtable[hash] = i; + counter++; + return i; + } + +public: + class iterator + { + new_dict *ptr; + int index; + public: + iterator(new_dict *ptr, int index) : ptr(ptr), index(index) { } + iterator operator++() { do index++; while (index != int(ptr->entries.size()) && ptr->entries[index].is_free()); return *this; } + iterator operator--() { do index--; while (index != 0 && ptr->entries[index].is_free()); return *this; } + bool operator==(const iterator &other) const { return index == other.index; } + bool operator!=(const iterator &other) const { return index != other.index; } + std::pair &operator*() { return ptr->entries[index].udata; } + }; + + new_dict() + { + init(); + } + + template + new_dict(InputIterator first, InputIterator last) + { + init(); + insert(first, last); + } + + template + void insert(InputIterator first, InputIterator last) + { + for (; first != last; ++first) + insert(*first); + } + + iterator insert(const std::pair &value) + { + int hash = mkhash(value.first); + int i = lookup_index(value.first, hash); + if (i >= 0) + return iterator(this, i); + i = insert_at(value, hash); + return iterator(this, i); + } + + void erase(const K &key) + { + int hash = mkhash(key); + do_erase(key, hash); + } + + int count(const K &key) + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + return i < 0 ? 0 : 1; + } + + T& operator[](const K &key) + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + if (i < 0) + i = insert_at(std::pair(key, T()), hash); + return entries[i].udata.second; + } + + iterator begin() { int index = 0; while (index != int(entries.size()) && entries[index].is_free()) index++; return iterator(this, index); } + iterator end() { return iterator(this, entries.size()); } +}; + +#endif diff --git a/kernel/log.cc b/kernel/log.cc index 0773429a6..677884c97 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -301,7 +301,7 @@ void log_cell(RTLIL::Cell *cell, std::string indent) // --------------------------------------------------- #ifdef YOSYS_ENABLE_COVER -std::map> extra_coverage_data; +new_dict> extra_coverage_data; void cover_extra(std::string parent, std::string id, bool increment) { if (extra_coverage_data.count(id) == 0) { @@ -314,9 +314,9 @@ void cover_extra(std::string parent, std::string id, bool increment) { extra_coverage_data[id].second++; } -std::map> get_coverage_data() +new_dict> get_coverage_data() { - std::map> coverage_data; + new_dict> coverage_data; for (auto &it : pass_register) { std::string key = stringf("passes.%s", it.first.c_str()); diff --git a/kernel/log.h b/kernel/log.h index 278e35b41..eec071991 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -106,10 +106,10 @@ struct CoverData { extern "C" struct CoverData __start_yosys_cover_list[]; extern "C" struct CoverData __stop_yosys_cover_list[]; -extern std::map> extra_coverage_data; +extern new_dict> extra_coverage_data; void cover_extra(std::string parent, std::string id, bool increment = true); -std::map> get_coverage_data(); +new_dict> get_coverage_data(); #define cover_list(_id, ...) do { cover(_id); \ std::string r = cover_list_worker(_id, __VA_ARGS__); \ diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 2d3d83f42..28fdeecdd 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2171,7 +2171,7 @@ RTLIL::SigSpec::SigSpec(std::vector bits) RTLIL::SigSpec::SigSpec(nodict bits) { - cover("kernel.rtlil.sigspec.init.stdset_bits"); + cover("kernel.rtlil.sigspec.init.nodict_bits"); width_ = 0; hash_ = 0; diff --git a/kernel/yosys.h b/kernel/yosys.h index e2daabfae..b14852eaf 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -126,6 +126,7 @@ YOSYS_NAMESPACE_BEGIN #define dict std::unordered_map #define nodict std::unordered_set +#include "kernel/hashmap.h" using std::vector; namespace RTLIL { From 9e6fb0b02ccf209528ead026de8eef0a8a0d7740 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 26 Dec 2014 21:35:22 +0100 Subject: [PATCH 184/492] Replaced std::unordered_map as implementation for Yosys::dict --- backends/ilang/ilang_backend.cc | 34 ++-- backends/verilog/verilog_backend.cc | 50 +++--- kernel/cost.h | 14 +- kernel/hashmap.h | 230 +++++++++++++++++++++++++--- kernel/log.cc | 6 +- kernel/log.h | 4 +- kernel/rtlil.cc | 22 +-- kernel/rtlil.h | 32 +++- kernel/yosys.h | 1 - passes/opt/opt_const.cc | 2 +- passes/opt/opt_share.cc | 2 +- passes/tests/test_autotb.cc | 24 +-- 12 files changed, 318 insertions(+), 103 deletions(-) diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index 19c2805ca..dd5b6f3ce 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -103,7 +103,7 @@ void ILANG_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, boo dump_sigchunk(f, sig.as_chunk(), autoint); } else { f << stringf("{ "); - for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); it++) { + for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); ++it) { dump_sigchunk(f, *it, false); f << stringf(" "); } @@ -115,7 +115,7 @@ void ILANG_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL:: { std::map sorted_attributes(wire->attributes.begin(), wire->attributes.end()); - for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); it++) { + for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); ++it) { f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); f << stringf("\n"); @@ -140,7 +140,7 @@ void ILANG_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL { std::map sorted_attributes(memory->attributes.begin(), memory->attributes.end()); - for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); it++) { + for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); ++it) { f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); f << stringf("\n"); @@ -159,18 +159,18 @@ void ILANG_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL:: std::map sorted_parameters(cell->parameters.begin(), cell->parameters.end()); std::map sorted_connections(cell->connections().begin(), cell->connections().end()); - for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); it++) { + for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); ++it) { f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); f << stringf("\n"); } f << stringf("%s" "cell %s %s\n", indent.c_str(), cell->type.c_str(), cell->name.c_str()); - for (auto it = sorted_parameters.begin(); it != sorted_parameters.end(); it++) { + for (auto it = sorted_parameters.begin(); it != sorted_parameters.end(); ++it) { f << stringf("%s parameter%s %s ", indent.c_str(), (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "", it->first.c_str()); dump_const(f, it->second); f << stringf("\n"); } - for (auto it = sorted_connections.begin(); it != sorted_connections.end(); it++) { + for (auto it = sorted_connections.begin(); it != sorted_connections.end(); ++it) { f << stringf("%s connect %s ", indent.c_str(), it->first.c_str()); dump_sigspec(f, it->second); f << stringf("\n"); @@ -180,7 +180,7 @@ void ILANG_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL:: void ILANG_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs) { - for (auto it = cs->actions.begin(); it != cs->actions.end(); it++) + for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it) { f << stringf("%s" "assign ", indent.c_str()); dump_sigspec(f, it->first); @@ -189,13 +189,13 @@ void ILANG_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, con f << stringf("\n"); } - for (auto it = cs->switches.begin(); it != cs->switches.end(); it++) + for (auto it = cs->switches.begin(); it != cs->switches.end(); ++it) dump_proc_switch(f, indent, *it); } void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw) { - for (auto it = sw->attributes.begin(); it != sw->attributes.end(); it++) { + for (auto it = sw->attributes.begin(); it != sw->attributes.end(); ++it) { f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); f << stringf("\n"); @@ -205,7 +205,7 @@ void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const dump_sigspec(f, sw->signal); f << stringf("\n"); - for (auto it = sw->cases.begin(); it != sw->cases.end(); it++) + for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) { f << stringf("%s case ", indent.c_str()); for (size_t i = 0; i < (*it)->compare.size(); i++) { @@ -237,7 +237,7 @@ void ILANG_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT case RTLIL::STi: f << stringf("init\n"); break; } - for (auto it = sy->actions.begin(); it != sy->actions.end(); it++) { + for (auto it = sy->actions.begin(); it != sy->actions.end(); ++it) { f << stringf("%s update ", indent.c_str()); dump_sigspec(f, it->first); f << stringf(" "); @@ -248,14 +248,14 @@ void ILANG_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT void ILANG_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc) { - for (auto it = proc->attributes.begin(); it != proc->attributes.end(); it++) { + for (auto it = proc->attributes.begin(); it != proc->attributes.end(); ++it) { f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); f << stringf("\n"); } f << stringf("%s" "process %s\n", indent.c_str(), proc->name.c_str()); dump_proc_case_body(f, indent + " ", &proc->root_case); - for (auto it = proc->syncs.begin(); it != proc->syncs.end(); it++) + for (auto it = proc->syncs.begin(); it != proc->syncs.end(); ++it) dump_proc_sync(f, indent + " ", *it); f << stringf("%s" "end\n", indent.c_str()); } @@ -276,7 +276,7 @@ void ILANG_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu if (print_header) { - for (auto it = module->attributes.begin(); it != module->attributes.end(); it++) { + for (auto it = module->attributes.begin(); it != module->attributes.end(); ++it) { f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); f << stringf("\n"); @@ -336,7 +336,7 @@ void ILANG_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu } bool first_conn_line = true; - for (auto it = module->connections().begin(); it != module->connections().end(); it++) { + for (auto it = module->connections().begin(); it != module->connections().end(); ++it) { bool show_conn = !only_selected; if (only_selected) { RTLIL::SigSpec sigs = it->first; @@ -366,7 +366,7 @@ void ILANG_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl if (!flag_m) { int count_selected_mods = 0; - for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) { + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { if (design->selected_whole_module(it->first)) flag_m = true; if (design->selected(it->second)) @@ -382,7 +382,7 @@ void ILANG_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl f << stringf("autoidx %d\n", autoidx); } - for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) { + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { if (!only_selected || design->selected(it->second)) { if (only_selected) f << stringf("\n"); diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index ffaf9ec07..be9479301 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -74,22 +74,22 @@ void reset_auto_counter(RTLIL::Module *module) reset_auto_counter_id(module->name, false); - for (auto it = module->wires_.begin(); it != module->wires_.end(); it++) + for (auto it = module->wires_.begin(); it != module->wires_.end(); ++it) reset_auto_counter_id(it->second->name, true); - for (auto it = module->cells_.begin(); it != module->cells_.end(); it++) { + for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it) { reset_auto_counter_id(it->second->name, true); reset_auto_counter_id(it->second->type, false); } - for (auto it = module->processes.begin(); it != module->processes.end(); it++) + for (auto it = module->processes.begin(); it != module->processes.end(); ++it) reset_auto_counter_id(it->second->name, false); auto_name_digits = 1; for (size_t i = 10; i < auto_name_offset + auto_name_map.size(); i = i*10) auto_name_digits++; - for (auto it = auto_name_map.begin(); it != auto_name_map.end(); it++) + for (auto it = auto_name_map.begin(); it != auto_name_map.end(); ++it) log(" renaming `%s' to `_%0*d_'.\n", it->first.c_str(), auto_name_digits, auto_name_offset + it->second); } @@ -237,7 +237,7 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig) dump_sigchunk(f, sig.as_chunk()); } else { f << stringf("{ "); - for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); it++) { + for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); ++it) { if (it != sig.chunks().rbegin()) f << stringf(", "); dump_sigchunk(f, *it, true); @@ -250,7 +250,7 @@ void dump_attributes(std::ostream &f, std::string indent, dictfirst).c_str()); f << stringf(" = "); dump_const(f, it->second); @@ -744,7 +744,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) if (cell->parameters.size() > 0) { f << stringf(" #("); - for (auto it = cell->parameters.begin(); it != cell->parameters.end(); it++) { + for (auto it = cell->parameters.begin(); it != cell->parameters.end(); ++it) { if (it != cell->parameters.begin()) f << stringf(","); f << stringf("\n%s .%s(", indent.c_str(), id(it->first).c_str()); @@ -766,7 +766,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) for (int i = 1; true; i++) { char str[16]; snprintf(str, 16, "$%d", i); - for (auto it = cell->connections().begin(); it != cell->connections().end(); it++) { + for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) { if (it->first != str) continue; if (!first_arg) @@ -780,7 +780,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) break; found_numbered_port:; } - for (auto it = cell->connections().begin(); it != cell->connections().end(); it++) { + for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) { if (numbered_ports.count(it->first)) continue; if (!first_arg) @@ -812,7 +812,7 @@ void dump_case_body(std::ostream &f, std::string indent, RTLIL::CaseRule *cs, bo if (!omit_trailing_begin && number_of_stmts >= 2) f << stringf("%s" "begin\n", indent.c_str()); - for (auto it = cs->actions.begin(); it != cs->actions.end(); it++) { + for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it) { if (it->first.size() == 0) continue; f << stringf("%s ", indent.c_str()); @@ -822,7 +822,7 @@ void dump_case_body(std::ostream &f, std::string indent, RTLIL::CaseRule *cs, bo f << stringf(";\n"); } - for (auto it = cs->switches.begin(); it != cs->switches.end(); it++) + for (auto it = cs->switches.begin(); it != cs->switches.end(); ++it) dump_proc_switch(f, indent + " ", *it); if (!omit_trailing_begin && number_of_stmts == 0) @@ -836,7 +836,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw { if (sw->signal.size() == 0) { f << stringf("%s" "begin\n", indent.c_str()); - for (auto it = sw->cases.begin(); it != sw->cases.end(); it++) { + for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) { if ((*it)->compare.size() == 0) dump_case_body(f, indent + " ", *it); } @@ -848,7 +848,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw dump_sigspec(f, sw->signal); f << stringf(")\n"); - for (auto it = sw->cases.begin(); it != sw->cases.end(); it++) { + for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) { f << stringf("%s ", indent.c_str()); if ((*it)->compare.size() == 0) f << stringf("default"); @@ -868,11 +868,11 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw void case_body_find_regs(RTLIL::CaseRule *cs) { - for (auto it = cs->switches.begin(); it != cs->switches.end(); it++) + for (auto it = cs->switches.begin(); it != cs->switches.end(); ++it) for (auto it2 = (*it)->cases.begin(); it2 != (*it)->cases.end(); it2++) case_body_find_regs(*it2); - for (auto it = cs->actions.begin(); it != cs->actions.end(); it++) { + for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it) { for (auto &c : it->first.chunks()) if (c.wire != NULL) reg_wires.insert(c.wire->name); @@ -883,7 +883,7 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo { if (find_regs) { case_body_find_regs(&proc->root_case); - for (auto it = proc->syncs.begin(); it != proc->syncs.end(); it++) + for (auto it = proc->syncs.begin(); it != proc->syncs.end(); ++it) for (auto it2 = (*it)->actions.begin(); it2 != (*it)->actions.end(); it2++) { for (auto &c : it2->first.chunks()) if (c.wire != NULL) @@ -937,7 +937,7 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo } } - for (auto it = sync->actions.begin(); it != sync->actions.end(); it++) { + for (auto it = sync->actions.begin(); it != sync->actions.end(); ++it) { if (it->first.size() == 0) continue; f << stringf("%s ", indent.c_str()); @@ -958,7 +958,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) active_module = module; f << stringf("\n"); - for (auto it = module->processes.begin(); it != module->processes.end(); it++) + for (auto it = module->processes.begin(); it != module->processes.end(); ++it) dump_process(f, indent + " ", it->second, true); if (!noexpr) @@ -996,7 +996,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) bool keep_running = true; for (int port_id = 1; keep_running; port_id++) { keep_running = false; - for (auto it = module->wires_.begin(); it != module->wires_.end(); it++) { + for (auto it = module->wires_.begin(); it != module->wires_.end(); ++it) { RTLIL::Wire *wire = it->second; if (wire->port_id == port_id) { if (port_id != 1) @@ -1009,19 +1009,19 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) } f << stringf(");\n"); - for (auto it = module->wires_.begin(); it != module->wires_.end(); it++) + for (auto it = module->wires_.begin(); it != module->wires_.end(); ++it) dump_wire(f, indent + " ", it->second); - for (auto it = module->memories.begin(); it != module->memories.end(); it++) + for (auto it = module->memories.begin(); it != module->memories.end(); ++it) dump_memory(f, indent + " ", it->second); - for (auto it = module->cells_.begin(); it != module->cells_.end(); it++) + for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it) dump_cell(f, indent + " ", it->second); - for (auto it = module->processes.begin(); it != module->processes.end(); it++) + for (auto it = module->processes.begin(); it != module->processes.end(); ++it) dump_process(f, indent + " ", it->second); - for (auto it = module->connections().begin(); it != module->connections().end(); it++) + for (auto it = module->connections().begin(); it != module->connections().end(); ++it) dump_conn(f, indent + " ", it->first, it->second); f << stringf("%s" "endmodule\n", indent.c_str()); @@ -1133,7 +1133,7 @@ struct VerilogBackend : public Backend { extra_args(f, filename, args, argidx); *f << stringf("/* Generated by %s */\n", yosys_version_str); - for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) { + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { if (it->second->get_bool_attribute("\\blackbox") != blackboxes) continue; if (selected && !design->selected_whole_module(it->first)) { diff --git a/kernel/cost.h b/kernel/cost.h index 1b4166e00..c6c631e0a 100644 --- a/kernel/cost.h +++ b/kernel/cost.h @@ -24,10 +24,10 @@ YOSYS_NAMESPACE_BEGIN -int get_cell_cost(RTLIL::Cell *cell, dict *mod_cost_cache = nullptr); +int get_cell_cost(RTLIL::Cell *cell, dict *mod_cost_cache = nullptr); int get_cell_cost(RTLIL::IdString type, const dict ¶meters = dict(), - RTLIL::Design *design = nullptr, dict *mod_cost_cache = nullptr) + RTLIL::Design *design = nullptr, dict *mod_cost_cache = nullptr) { static dict gate_cost = { { "$_BUF_", 1 }, @@ -55,18 +55,18 @@ int get_cell_cost(RTLIL::IdString type, const dictattributes.count("\\cost")) return mod->attributes.at("\\cost").as_int(); - dict local_mod_cost_cache; + dict local_mod_cost_cache; if (mod_cost_cache == nullptr) mod_cost_cache = &local_mod_cost_cache; - if (mod_cost_cache->count(mod)) - return mod_cost_cache->at(mod); + if (mod_cost_cache->count(mod->name)) + return mod_cost_cache->at(mod->name); int module_cost = 1; for (auto c : mod->cells()) module_cost += get_cell_cost(c, mod_cost_cache); - (*mod_cost_cache)[mod] = module_cost; + (*mod_cost_cache)[mod->name] = module_cost; return module_cost; } @@ -74,7 +74,7 @@ int get_cell_cost(RTLIL::IdString type, const dict *mod_cost_cache) +int get_cell_cost(RTLIL::Cell *cell, dict *mod_cost_cache) { return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache); } diff --git a/kernel/hashmap.h b/kernel/hashmap.h index bd4fc4d22..d5f8c4e98 100644 --- a/kernel/hashmap.h +++ b/kernel/hashmap.h @@ -19,6 +19,7 @@ #ifndef YOSYS_HASHMAP_H +#include #include #include @@ -27,28 +28,28 @@ inline unsigned int mkhash(unsigned int a, unsigned int b) { } template struct hash_ops { - bool cmp(const T &a, const T &b) { + bool cmp(const T &a, const T &b) const { return a == b; } - unsigned int hash(const T &a) { + unsigned int hash(const T &a) const { return a.hash(); } }; template<> struct hash_ops { - bool cmp(int a, int b) { + bool cmp(int a, int b) const { return a == b; } - unsigned int hash(int a) { + unsigned int hash(int a) const { return a; } }; template<> struct hash_ops { - bool cmp(const std::string &a, const std::string &b) { + bool cmp(const std::string &a, const std::string &b) const { return a == b; } - unsigned int hash(const std::string &a) { + unsigned int hash(const std::string &a) const { unsigned int v = 0; for (auto c : a) v = mkhash(v, c); @@ -56,14 +57,25 @@ template<> struct hash_ops { } }; +struct hash_ptr_ops { + bool cmp(const void *a, const void *b) const { + return a == b; + } + unsigned int hash(const void *a) const { + return (unsigned long)a; + } +}; + template> -class new_dict +class dict { struct entry_t { int link; std::pair udata; + entry_t() : link(-1) { } + entry_t(const std::pair &udata) : link(1), udata(udata) { } bool is_free() const { return link < 0; } int get_next() const { return (link > 0 ? link : -link) - 2; } @@ -79,17 +91,61 @@ class new_dict void init() { + free_list = -1; counter = 0; - entries.resize(61); + } + + void init_from(const dict &other) + { + hashtable.clear(); + entries.clear(); + + counter = other.size(); + int new_size = grow_size(counter); + entries.reserve(new_size); + + for (auto &it : other) + entries.push_back(entry_t(it)); + entries.resize(new_size); rehash(); } - int mkhash(const K &key) + size_t grow_size(size_t old_size) { - return ops.hash(key) % int(hashtable.size()); + if (old_size < 53) return 53; + if (old_size < 113) return 113; + if (old_size < 251) return 251; + if (old_size < 503) return 503; + if (old_size < 1130) return 1130; + if (old_size < 2510) return 2510; + if (old_size < 5030) return 5030; + if (old_size < 11300) return 11300; + if (old_size < 25100) return 25100; + if (old_size < 50300) return 50300; + if (old_size < 113000) return 113000; + if (old_size < 251000) return 251000; + if (old_size < 503000) return 503000; + if (old_size < 1130000) return 1130000; + if (old_size < 2510000) return 2510000; + if (old_size < 5030000) return 5030000; + if (old_size < 11300000) return 11300000; + if (old_size < 25100000) return 25100000; + if (old_size < 50300000) return 50300000; + if (old_size < 113000000) return 113000000; + if (old_size < 251000000) return 251000000; + if (old_size < 503000000) return 503000000; + if (old_size < 1130000000) return 1130000000; + throw std::length_error("maximum size for dict reached"); + } + + int mkhash(const K &key) const + { + unsigned int hash = 0; + if (!hashtable.empty()) + hash = ops.hash(key) % (unsigned int)(hashtable.size()); + return hash; } -public: void rehash() { free_list = -1; @@ -112,7 +168,7 @@ public: void do_erase(const K &key, int hash) { int last_index = -1; - int index = hashtable[hash]; + int index = hashtable.empty() ? -1 : hashtable[hash]; while (1) { if (index < 0) return; @@ -124,7 +180,8 @@ public: entries[index].udata = std::pair(); entries[index].set_next_free(free_list); free_list = index; - counter--; + if (--counter == 0) + init(); return; } last_index = index; @@ -132,9 +189,9 @@ public: } } - int lookup_index(const K &key, int hash) + int lookup_index(const K &key, int hash) const { - int index = hashtable[hash]; + int index = hashtable.empty() ? -1 : hashtable[hash]; while (1) { if (index < 0) return -1; @@ -149,7 +206,7 @@ public: if (free_list < 0) { int i = entries.size(); - entries.resize(2*entries.size()); + entries.resize(grow_size(i)); entries[i].udata = value; entries[i].set_next_used(0); counter++; @@ -169,24 +226,74 @@ public: public: class iterator { - new_dict *ptr; + dict *ptr; int index; public: - iterator(new_dict *ptr, int index) : ptr(ptr), index(index) { } + iterator() { } + iterator(dict *ptr, int index) : ptr(ptr), index(index) { } iterator operator++() { do index++; while (index != int(ptr->entries.size()) && ptr->entries[index].is_free()); return *this; } iterator operator--() { do index--; while (index != 0 && ptr->entries[index].is_free()); return *this; } bool operator==(const iterator &other) const { return index == other.index; } bool operator!=(const iterator &other) const { return index != other.index; } std::pair &operator*() { return ptr->entries[index].udata; } + std::pair *operator->() { return &ptr->entries[index].udata; } + const std::pair &operator*() const { return ptr->entries[index].udata; } + const std::pair *operator->() const { return &ptr->entries[index].udata; } }; - new_dict() + class const_iterator + { + const dict *ptr; + int index; + public: + const_iterator() { } + const_iterator(const dict *ptr, int index) : ptr(ptr), index(index) { } + const_iterator operator++() { do index++; while (index != int(ptr->entries.size()) && ptr->entries[index].is_free()); return *this; } + const_iterator operator--() { do index--; while (index != 0 && ptr->entries[index].is_free()); return *this; } + bool operator==(const const_iterator &other) const { return index == other.index; } + bool operator!=(const const_iterator &other) const { return index != other.index; } + const std::pair &operator*() const { return ptr->entries[index].udata; } + const std::pair *operator->() const { return &ptr->entries[index].udata; } + }; + + dict() { init(); } + dict(const dict &other) + { + init_from(other); + } + + dict(dict &&other) + { + free_list = -1; + counter = 0; + swap(other); + } + + dict &operator=(const dict &other) { + clear(); + init_from(other); + return *this; + } + + dict &operator=(dict &&other) { + clear(); + swap(other); + return *this; + } + + dict(const std::initializer_list> &list) + { + init(); + for (auto &it : list) + insert(it); + } + template - new_dict(InputIterator first, InputIterator last) + dict(InputIterator first, InputIterator last) { init(); insert(first, last); @@ -215,13 +322,55 @@ public: do_erase(key, hash); } - int count(const K &key) + void erase(const iterator it) + { + int hash = mkhash(it->first); + do_erase(it->first, hash); + } + + int count(const K &key) const { int hash = mkhash(key); int i = lookup_index(key, hash); return i < 0 ? 0 : 1; } + iterator find(const K &key) + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + if (i < 0) + return end(); + return iterator(this, i); + } + + const_iterator find(const K &key) const + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + if (i < 0) + return end(); + return const_iterator(this, i); + } + + T& at(const K &key) + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + if (i < 0) + throw std::out_of_range("dict::at()"); + return entries[i].udata.second; + } + + const T& at(const K &key) const + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + if (i < 0) + throw std::out_of_range("dict::at()"); + return entries[i].udata.second; + } + T& operator[](const K &key) { int hash = mkhash(key); @@ -231,8 +380,47 @@ public: return entries[i].udata.second; } + void swap(dict &other) + { + hashtable.swap(other.hashtable); + entries.swap(other.entries); + std::swap(free_list, other.free_list); + std::swap(counter, other.counter); + } + + bool operator==(const dict &other) const { + if (counter != other.counter) + return false; + if (counter == 0) + return true; + if (entries.size() < other.entries.size()) + for (auto &it : *this) { + auto oit = other.find(it.first); + if (oit == other.end() || oit->second != it.second) + return false; + } + else + for (auto &oit : other) { + auto it = find(oit.first); + if (it == end() || it->second != oit.second) + return false; + } + return true; + } + + bool operator!=(const dict &other) const { + return !(*this == other); + } + + size_t size() const { return counter; } + bool empty() const { return counter == 0; } + void clear() { hashtable.clear(); entries.clear(); init(); } + iterator begin() { int index = 0; while (index != int(entries.size()) && entries[index].is_free()) index++; return iterator(this, index); } iterator end() { return iterator(this, entries.size()); } + + const_iterator begin() const { int index = 0; while (index != int(entries.size()) && entries[index].is_free()) index++; return const_iterator(this, index); } + const_iterator end() const { return const_iterator(this, entries.size()); } }; #endif diff --git a/kernel/log.cc b/kernel/log.cc index 677884c97..5b18e3d6c 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -301,7 +301,7 @@ void log_cell(RTLIL::Cell *cell, std::string indent) // --------------------------------------------------- #ifdef YOSYS_ENABLE_COVER -new_dict> extra_coverage_data; +dict> extra_coverage_data; void cover_extra(std::string parent, std::string id, bool increment) { if (extra_coverage_data.count(id) == 0) { @@ -314,9 +314,9 @@ void cover_extra(std::string parent, std::string id, bool increment) { extra_coverage_data[id].second++; } -new_dict> get_coverage_data() +dict> get_coverage_data() { - new_dict> coverage_data; + dict> coverage_data; for (auto &it : pass_register) { std::string key = stringf("passes.%s", it.first.c_str()); diff --git a/kernel/log.h b/kernel/log.h index eec071991..9bb2b3621 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -106,10 +106,10 @@ struct CoverData { extern "C" struct CoverData __start_yosys_cover_list[]; extern "C" struct CoverData __stop_yosys_cover_list[]; -extern new_dict> extra_coverage_data; +extern dict> extra_coverage_data; void cover_extra(std::string parent, std::string id, bool increment = true); -new_dict> get_coverage_data(); +dict> get_coverage_data(); #define cover_list(_id, ...) do { cover(_id); \ std::string r = cover_list_worker(_id, __VA_ARGS__); \ diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 28fdeecdd..05160b869 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -30,7 +30,7 @@ YOSYS_NAMESPACE_BEGIN RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard; std::vector RTLIL::IdString::global_refcount_storage_; std::vector RTLIL::IdString::global_id_storage_; -dict RTLIL::IdString::global_id_index_; +dict RTLIL::IdString::global_id_index_; std::vector RTLIL::IdString::global_free_idx_list_; RTLIL::Const::Const() @@ -242,7 +242,7 @@ RTLIL::Design::Design() RTLIL::Design::~Design() { - for (auto it = modules_.begin(); it != modules_.end(); it++) + for (auto it = modules_.begin(); it != modules_.end(); ++it) delete it->second; } @@ -454,13 +454,13 @@ RTLIL::Module::Module() RTLIL::Module::~Module() { - for (auto it = wires_.begin(); it != wires_.end(); it++) + for (auto it = wires_.begin(); it != wires_.end(); ++it) delete it->second; - for (auto it = memories.begin(); it != memories.end(); it++) + for (auto it = memories.begin(); it != memories.end(); ++it) delete it->second; - for (auto it = cells_.begin(); it != cells_.end(); it++) + for (auto it = cells_.begin(); it != cells_.end(); ++it) delete it->second; - for (auto it = processes.begin(); it != processes.end(); it++) + for (auto it = processes.begin(); it != processes.end(); ++it) delete it->second; } @@ -2258,7 +2258,7 @@ void RTLIL::SigSpec::unpack() const #define DJB2(_hash, _value) (_hash) = (((_hash) << 5) + (_hash)) + (_value) -void RTLIL::SigSpec::hash() const +void RTLIL::SigSpec::updhash() const { RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; @@ -2721,8 +2721,8 @@ bool RTLIL::SigSpec::operator <(const RTLIL::SigSpec &other) const if (chunks_.size() != other.chunks_.size()) return chunks_.size() < other.chunks_.size(); - hash(); - other.hash(); + updhash(); + other.updhash(); if (hash_ != other.hash_) return hash_ < other.hash_; @@ -2753,8 +2753,8 @@ bool RTLIL::SigSpec::operator ==(const RTLIL::SigSpec &other) const if (chunks_.size() != chunks_.size()) return false; - hash(); - other.hash(); + updhash(); + other.updhash(); if (hash_ != other.hash_) return false; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index e684ba4ae..756cca71c 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -124,6 +124,21 @@ namespace RTLIL } }; + struct char_ptr_ops { + bool cmp(const char *a, const char *b) const { + for (int i = 0; a[i] || b[i]; i++) + if (a[i] != b[i]) + return false; + return true; + } + unsigned int hash(const char *a) const { + size_t hash = 5381; + while (*a) + hash = mkhash(hash, *(a++)); + return hash; + } + }; + static struct destruct_guard_t { bool ok; // POD, will be initialized to zero destruct_guard_t() { ok = true; } @@ -132,7 +147,7 @@ namespace RTLIL static std::vector global_refcount_storage_; static std::vector global_id_storage_; - static dict global_id_index_; + static dict global_id_index_; static std::vector global_free_idx_list_; static inline int get_reference(int idx) @@ -263,6 +278,10 @@ namespace RTLIL *this = IdString(); } + unsigned int hash() const { + return index_; + } + // The following is a helper key_compare class. Instead of for example nodict // use nodict> if the order of cells in the // set has an influence on the algorithm. @@ -538,6 +557,7 @@ struct RTLIL::SigBit bool operator <(const RTLIL::SigBit &other) const; bool operator ==(const RTLIL::SigBit &other) const; bool operator !=(const RTLIL::SigBit &other) const; + unsigned int hash() const; }; struct RTLIL::SigSpecIterator : public std::iterator @@ -572,7 +592,7 @@ private: void pack() const; void unpack() const; - void hash() const; + void updhash() const; inline bool packed() const { return bits_.empty(); @@ -710,6 +730,8 @@ public: operator std::vector() const { return chunks(); } operator std::vector() const { return bits(); } + unsigned int hash() const { if (!hash_) updhash(); return hash_; }; + #ifndef NDEBUG void check() const; #else @@ -1213,6 +1235,12 @@ inline bool RTLIL::SigBit::operator!=(const RTLIL::SigBit &other) const { return (wire != other.wire) || (wire ? (offset != other.offset) : (data != other.data)); } +inline unsigned int RTLIL::SigBit::hash() const { + if (wire) + return wire->name.hash() * 33 + offset; + return data; +} + inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const { return (*sig_p)[index]; } diff --git a/kernel/yosys.h b/kernel/yosys.h index b14852eaf..9b76d28c6 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -124,7 +124,6 @@ YOSYS_NAMESPACE_BEGIN -#define dict std::unordered_map #define nodict std::unordered_set #include "kernel/hashmap.h" using std::vector; diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc index 7f800bde9..9c1a18782 100644 --- a/passes/opt/opt_const.cc +++ b/passes/opt/opt_const.cc @@ -199,7 +199,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons dict invert_map; TopoSort> cells; - dict> cell_to_inbit; + dict, hash_ptr_ops> cell_to_inbit; dict> outbit_to_cell; for (auto cell : module->cells()) diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index c581b749e..9bc308873 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -41,7 +41,7 @@ struct OptShareWorker CellTypes ct; int total_count; #ifdef USE_CELL_HASH_CACHE - dict cell_hash_cache; + dict cell_hash_cache; #endif #ifdef USE_CELL_HASH_CACHE diff --git a/passes/tests/test_autotb.cc b/passes/tests/test_autotb.cc index 9713ea061..74ee0f5a9 100644 --- a/passes/tests/test_autotb.cc +++ b/passes/tests/test_autotb.cc @@ -92,7 +92,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter) f << stringf("end\n"); f << stringf("endtask\n\n"); - for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { std::map signal_in; std::map signal_const; @@ -106,7 +106,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter) int count_ports = 0; log("Generating test bench for module `%s'.\n", it->first.c_str()); - for (auto it2 = mod->wires_.begin(); it2 != mod->wires_.end(); it2++) { + for (auto it2 = mod->wires_.begin(); it2 != mod->wires_.end(); ++it2) { RTLIL::Wire *wire = it2->second; if (wire->port_output) { count_ports++; @@ -115,8 +115,8 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter) } else if (wire->port_input) { count_ports++; bool is_clksignal = wire->get_bool_attribute("\\gentb_clock"); - for (auto it3 = mod->processes.begin(); it3 != mod->processes.end(); it3++) - for (auto it4 = it3->second->syncs.begin(); it4 != it3->second->syncs.end(); it4++) { + for (auto it3 = mod->processes.begin(); it3 != mod->processes.end(); ++it3) + for (auto it4 = it3->second->syncs.begin(); it4 != it3->second->syncs.end(); ++it4) { if ((*it4)->type == RTLIL::ST0 || (*it4)->type == RTLIL::ST1) continue; RTLIL::SigSpec &signal = (*it4)->signal; @@ -135,7 +135,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter) } } f << stringf("%s %s(\n", id(mod->name.str()).c_str(), idy("uut", mod->name.str()).c_str()); - for (auto it2 = mod->wires_.begin(); it2 != mod->wires_.end(); it2++) { + for (auto it2 = mod->wires_.begin(); it2 != mod->wires_.end(); ++it2) { RTLIL::Wire *wire = it2->second; if (wire->port_output || wire->port_input) f << stringf("\t.%s(%s)%s\n", id(wire->name.str()).c_str(), @@ -146,23 +146,23 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter) f << stringf("task %s;\n", idy(mod->name.str(), "reset").c_str()); f << stringf("begin\n"); int delay_counter = 0; - for (auto it = signal_in.begin(); it != signal_in.end(); it++) + for (auto it = signal_in.begin(); it != signal_in.end(); ++it) f << stringf("\t%s <= #%d 0;\n", it->first.c_str(), ++delay_counter*2); - for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) + for (auto it = signal_clk.begin(); it != signal_clk.end(); ++it) f << stringf("\t%s <= #%d 0;\n", it->first.c_str(), ++delay_counter*2); - for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) { + for (auto it = signal_clk.begin(); it != signal_clk.end(); ++it) { f << stringf("\t#100; %s <= 1;\n", it->first.c_str()); f << stringf("\t#100; %s <= 0;\n", it->first.c_str()); } delay_counter = 0; - for (auto it = signal_in.begin(); it != signal_in.end(); it++) + for (auto it = signal_in.begin(); it != signal_in.end(); ++it) f << stringf("\t%s <= #%d ~0;\n", it->first.c_str(), ++delay_counter*2); - for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) { + for (auto it = signal_clk.begin(); it != signal_clk.end(); ++it) { f << stringf("\t#100; %s <= 1;\n", it->first.c_str()); f << stringf("\t#100; %s <= 0;\n", it->first.c_str()); } delay_counter = 0; - for (auto it = signal_in.begin(); it != signal_in.end(); it++) { + for (auto it = signal_in.begin(); it != signal_in.end(); ++it) { if (signal_const.count(it->first) == 0) continue; f << stringf("\t%s <= #%d 'b%s;\n", it->first.c_str(), ++delay_counter*2, signal_const[it->first].c_str()); @@ -293,7 +293,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter) f << stringf("initial begin\n"); f << stringf("\t// $dumpfile(\"testbench.vcd\");\n"); f << stringf("\t// $dumpvars(0, testbench);\n"); - for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) if (!it->second->get_bool_attribute("\\gentb_skip")) f << stringf("\t%s;\n", idy(it->first.str(), "test").c_str()); f << stringf("\t$finish;\n"); From ec4751e55c11d7287dacd39fb61ad936995fc963 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 26 Dec 2014 21:59:41 +0100 Subject: [PATCH 185/492] Replaced std::unordered_set (nodict) with Yosys::pool --- kernel/hashmap.h | 352 +++++++++++++++++++++++++++++++++++++++ kernel/rtlil.cc | 30 ++-- kernel/rtlil.h | 132 +++------------ kernel/yosys.h | 1 - passes/cmds/delete.cc | 8 +- passes/cmds/splitnets.cc | 2 +- passes/opt/opt_clean.cc | 2 +- passes/opt/wreduce.cc | 4 +- 8 files changed, 394 insertions(+), 137 deletions(-) diff --git a/kernel/hashmap.h b/kernel/hashmap.h index d5f8c4e98..50098ac35 100644 --- a/kernel/hashmap.h +++ b/kernel/hashmap.h @@ -57,6 +57,21 @@ template<> struct hash_ops { } }; +struct hash_cstr_ops { + bool cmp(const char *a, const char *b) const { + for (int i = 0; a[i] || b[i]; i++) + if (a[i] != b[i]) + return false; + return true; + } + unsigned int hash(const char *a) const { + size_t hash = 5381; + while (*a) + hash = mkhash(hash, *(a++)); + return hash; + } +}; + struct hash_ptr_ops { bool cmp(const void *a, const void *b) const { return a == b; @@ -423,4 +438,341 @@ public: const_iterator end() const { return const_iterator(this, entries.size()); } }; +template> +class pool +{ + struct entry_t + { + int link; + K key; + + entry_t() : link(-1) { } + entry_t(const K &key) : link(1), key(key) { } + + bool is_free() const { return link < 0; } + int get_next() const { return (link > 0 ? link : -link) - 2; } + bool get_last() const { return get_next() == -1; } + void set_next_used(int next) { link = next + 2; } + void set_next_free(int next) { link = -(next + 2); } + }; + + std::vector hashtable; + std::vector entries; + int free_list, counter; + OPS ops; + + void init() + { + free_list = -1; + counter = 0; + } + + void init_from(const pool &other) + { + hashtable.clear(); + entries.clear(); + + counter = other.size(); + int new_size = grow_size(counter); + entries.reserve(new_size); + + for (auto &it : other) + entries.push_back(entry_t(it)); + entries.resize(new_size); + rehash(); + } + + size_t grow_size(size_t old_size) + { + if (old_size < 53) return 53; + if (old_size < 113) return 113; + if (old_size < 251) return 251; + if (old_size < 503) return 503; + if (old_size < 1130) return 1130; + if (old_size < 2510) return 2510; + if (old_size < 5030) return 5030; + if (old_size < 11300) return 11300; + if (old_size < 25100) return 25100; + if (old_size < 50300) return 50300; + if (old_size < 113000) return 113000; + if (old_size < 251000) return 251000; + if (old_size < 503000) return 503000; + if (old_size < 1130000) return 1130000; + if (old_size < 2510000) return 2510000; + if (old_size < 5030000) return 5030000; + if (old_size < 11300000) return 11300000; + if (old_size < 25100000) return 25100000; + if (old_size < 50300000) return 50300000; + if (old_size < 113000000) return 113000000; + if (old_size < 251000000) return 251000000; + if (old_size < 503000000) return 503000000; + if (old_size < 1130000000) return 1130000000; + throw std::length_error("maximum size for pool reached"); + } + + int mkhash(const K &key) const + { + unsigned int hash = 0; + if (!hashtable.empty()) + hash = ops.hash(key) % (unsigned int)(hashtable.size()); + return hash; + } + + void rehash() + { + free_list = -1; + + hashtable.resize(entries.size()); + for (auto &h : hashtable) + h = -1; + + for (int i = 0; i < int(entries.size()); i++) + if (entries[i].is_free()) { + entries[i].set_next_free(free_list); + free_list = i; + } else { + int hash = mkhash(entries[i].key); + entries[i].set_next_used(hashtable[hash]); + hashtable[hash] = i; + } + } + + void do_erase(const K &key, int hash) + { + int last_index = -1; + int index = hashtable.empty() ? -1 : hashtable[hash]; + while (1) { + if (index < 0) + return; + if (ops.cmp(entries[index].key, key)) { + if (last_index < 0) + hashtable[hash] = entries[index].get_next(); + else + entries[last_index].set_next_used(entries[index].get_next()); + entries[index].key = K(); + entries[index].set_next_free(free_list); + free_list = index; + if (--counter == 0) + init(); + return; + } + last_index = index; + index = entries[index].get_next(); + } + } + + int lookup_index(const K &key, int hash) const + { + int index = hashtable.empty() ? -1 : hashtable[hash]; + while (1) { + if (index < 0) + return -1; + if (ops.cmp(entries[index].key, key)) + return index; + index = entries[index].get_next(); + } + } + + int insert_at(const K &key, int hash) + { + if (free_list < 0) + { + int i = entries.size(); + entries.resize(grow_size(i)); + entries[i].key = key; + entries[i].set_next_used(0); + counter++; + rehash(); + return i; + } + + int i = free_list; + free_list = entries[i].get_next(); + entries[i].key = key; + entries[i].set_next_used(hashtable[hash]); + hashtable[hash] = i; + counter++; + return i; + } + +public: + class iterator + { + pool *ptr; + int index; + public: + iterator() { } + iterator(pool *ptr, int index) : ptr(ptr), index(index) { } + iterator operator++() { do index++; while (index != int(ptr->entries.size()) && ptr->entries[index].is_free()); return *this; } + iterator operator--() { do index--; while (index != 0 && ptr->entries[index].is_free()); return *this; } + bool operator==(const iterator &other) const { return index == other.index; } + bool operator!=(const iterator &other) const { return index != other.index; } + K &operator*() { return ptr->entries[index].key; } + K *operator->() { return &ptr->entries[index].key; } + const K &operator*() const { return ptr->entries[index].key; } + const K *operator->() const { return &ptr->entries[index].key; } + }; + + class const_iterator + { + const pool *ptr; + int index; + public: + const_iterator() { } + const_iterator(const pool *ptr, int index) : ptr(ptr), index(index) { } + const_iterator operator++() { do index++; while (index != int(ptr->entries.size()) && ptr->entries[index].is_free()); return *this; } + const_iterator operator--() { do index--; while (index != 0 && ptr->entries[index].is_free()); return *this; } + bool operator==(const const_iterator &other) const { return index == other.index; } + bool operator!=(const const_iterator &other) const { return index != other.index; } + const K &operator*() const { return ptr->entries[index].key; } + const K *operator->() const { return &ptr->entries[index].key; } + }; + + pool() + { + init(); + } + + pool(const pool &other) + { + init_from(other); + } + + pool(pool &&other) + { + free_list = -1; + counter = 0; + swap(other); + } + + pool &operator=(const pool &other) { + clear(); + init_from(other); + return *this; + } + + pool &operator=(pool &&other) { + clear(); + swap(other); + return *this; + } + + pool(const std::initializer_list &list) + { + init(); + for (auto &it : list) + insert(it); + } + + template + pool(InputIterator first, InputIterator last) + { + init(); + insert(first, last); + } + + template + void insert(InputIterator first, InputIterator last) + { + for (; first != last; ++first) + insert(*first); + } + + iterator insert(const K &key) + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + if (i >= 0) + return iterator(this, i); + i = insert_at(key, hash); + return iterator(this, i); + } + + void erase(const K &key) + { + int hash = mkhash(key); + do_erase(key, hash); + } + + void erase(const iterator it) + { + int hash = mkhash(it->first); + do_erase(it->first, hash); + } + + int count(const K &key) const + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + return i < 0 ? 0 : 1; + } + + iterator find(const K &key) + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + if (i < 0) + return end(); + return iterator(this, i); + } + + const_iterator find(const K &key) const + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + if (i < 0) + return end(); + return const_iterator(this, i); + } + + bool operator[](const K &key) const + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + return i >= 0; + } + + void swap(pool &other) + { + hashtable.swap(other.hashtable); + entries.swap(other.entries); + std::swap(free_list, other.free_list); + std::swap(counter, other.counter); + } + + bool operator==(const pool &other) const { + if (counter != other.counter) + return false; + if (counter == 0) + return true; + if (entries.size() < other.entries.size()) + for (auto &it : *this) { + auto oit = other.find(it.first); + if (oit == other.end() || oit->second != it.second) + return false; + } + else + for (auto &oit : other) { + auto it = find(oit.first); + if (it == end() || it->second != oit.second) + return false; + } + return true; + } + + bool operator!=(const pool &other) const { + return !(*this == other); + } + + size_t size() const { return counter; } + bool empty() const { return counter == 0; } + void clear() { hashtable.clear(); entries.clear(); init(); } + + iterator begin() { int index = 0; while (index != int(entries.size()) && entries[index].is_free()) index++; return iterator(this, index); } + iterator end() { return iterator(this, entries.size()); } + + const_iterator begin() const { int index = 0; while (index != int(entries.size()) && entries[index].is_free()) index++; return const_iterator(this, index); } + const_iterator end() const { return const_iterator(this, entries.size()); } +}; + #endif diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 05160b869..8f65f5273 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -30,7 +30,7 @@ YOSYS_NAMESPACE_BEGIN RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard; std::vector RTLIL::IdString::global_refcount_storage_; std::vector RTLIL::IdString::global_id_storage_; -dict RTLIL::IdString::global_id_index_; +dict RTLIL::IdString::global_id_index_; std::vector RTLIL::IdString::global_free_idx_list_; RTLIL::Const::Const() @@ -480,7 +480,7 @@ namespace { { RTLIL::Module *module; RTLIL::Cell *cell; - nodict expected_params, expected_ports; + pool expected_params, expected_ports; InternalCellChecker(RTLIL::Module *module, RTLIL::Cell *cell) : module(module), cell(cell) { } @@ -1132,7 +1132,7 @@ namespace { struct DeleteWireWorker { RTLIL::Module *module; - const nodict *wires_p; + const pool *wires_p; void operator()(RTLIL::SigSpec &sig) { std::vector chunks = sig; @@ -1146,7 +1146,7 @@ namespace { }; } -void RTLIL::Module::remove(const nodict &wires) +void RTLIL::Module::remove(const pool &wires) { log_assert(refcount_wires_ == 0); @@ -2169,9 +2169,9 @@ RTLIL::SigSpec::SigSpec(std::vector bits) check(); } -RTLIL::SigSpec::SigSpec(nodict bits) +RTLIL::SigSpec::SigSpec(pool bits) { - cover("kernel.rtlil.sigspec.init.nodict_bits"); + cover("kernel.rtlil.sigspec.init.pool_bits"); width_ = 0; hash_ = 0; @@ -2378,22 +2378,22 @@ void RTLIL::SigSpec::remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other void RTLIL::SigSpec::remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) { - nodict pattern_bits = pattern.to_sigbit_nodict(); + pool pattern_bits = pattern.to_sigbit_nodict(); remove2(pattern_bits, other); } -void RTLIL::SigSpec::remove(const nodict &pattern) +void RTLIL::SigSpec::remove(const pool &pattern) { remove2(pattern, NULL); } -void RTLIL::SigSpec::remove(const nodict &pattern, RTLIL::SigSpec *other) const +void RTLIL::SigSpec::remove(const pool &pattern, RTLIL::SigSpec *other) const { RTLIL::SigSpec tmp = *this; tmp.remove2(pattern, other); } -void RTLIL::SigSpec::remove2(const nodict &pattern, RTLIL::SigSpec *other) +void RTLIL::SigSpec::remove2(const pool &pattern, RTLIL::SigSpec *other) { if (other) cover("kernel.rtlil.sigspec.remove_other"); @@ -2439,11 +2439,11 @@ void RTLIL::SigSpec::remove2(const nodict &pattern, RTLIL::SigSpe RTLIL::SigSpec RTLIL::SigSpec::extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other) const { - nodict pattern_bits = pattern.to_sigbit_nodict(); + pool pattern_bits = pattern.to_sigbit_nodict(); return extract(pattern_bits, other); } -RTLIL::SigSpec RTLIL::SigSpec::extract(const nodict &pattern, const RTLIL::SigSpec *other) const +RTLIL::SigSpec RTLIL::SigSpec::extract(const pool &pattern, const RTLIL::SigSpec *other) const { if (other) cover("kernel.rtlil.sigspec.extract_other"); @@ -2943,12 +2943,12 @@ std::set RTLIL::SigSpec::to_sigbit_set() const return sigbits; } -nodict RTLIL::SigSpec::to_sigbit_nodict() const +pool RTLIL::SigSpec::to_sigbit_nodict() const { - cover("kernel.rtlil.sigspec.to_sigbit_nodict"); + cover("kernel.rtlil.sigspec.to_sigbit_pool"); pack(); - nodict sigbits; + pool sigbits; for (auto &c : chunks_) for (int i = 0; i < c.width; i++) sigbits.insert(RTLIL::SigBit(c, i)); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 756cca71c..ae37c350c 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -22,27 +22,6 @@ #ifndef RTLIL_H #define RTLIL_H -namespace std { - template<> struct hash { - size_t operator()(const Yosys::RTLIL::IdString &arg) const; - }; - template<> struct equal_to { - bool operator()(const Yosys::RTLIL::IdString &lhs, const Yosys::RTLIL::IdString &rhs) const; - }; - template<> struct hash { - size_t operator()(const Yosys::RTLIL::SigBit &arg) const; - }; - template<> struct equal_to { - bool operator()(const Yosys::RTLIL::SigBit &lhs, const Yosys::RTLIL::SigBit &rhs) const; - }; - template<> struct hash { - size_t operator()(const Yosys::RTLIL::SigSpec &arg) const; - }; - template<> struct equal_to { - bool operator()(const Yosys::RTLIL::SigSpec &lhs, const Yosys::RTLIL::SigSpec &rhs) const; - }; -} - YOSYS_NAMESPACE_BEGIN namespace RTLIL @@ -97,48 +76,6 @@ namespace RTLIL { // the global id string cache - struct char_ptr_cmp { - bool operator()(const char *a, const char *b) const { - for (int i = 0; a[i] || b[i]; i++) - if (a[i] != b[i]) - return a[i] < b[i]; - return false; - } - }; - - struct char_ptr_hash { - size_t operator()(const char *a) const { - size_t hash = 5381; - for (int c; (c = *a); a++) - hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ - return hash; - } - }; - - struct char_ptr_eq { - bool operator()(const char *a, const char *b) const { - for (int i = 0; a[i] || b[i]; i++) - if (a[i] != b[i]) - return false; - return true; - } - }; - - struct char_ptr_ops { - bool cmp(const char *a, const char *b) const { - for (int i = 0; a[i] || b[i]; i++) - if (a[i] != b[i]) - return false; - return true; - } - unsigned int hash(const char *a) const { - size_t hash = 5381; - while (*a) - hash = mkhash(hash, *(a++)); - return hash; - } - }; - static struct destruct_guard_t { bool ok; // POD, will be initialized to zero destruct_guard_t() { ok = true; } @@ -147,7 +84,7 @@ namespace RTLIL static std::vector global_refcount_storage_; static std::vector global_id_storage_; - static dict global_id_index_; + static dict global_id_index_; static std::vector global_free_idx_list_; static inline int get_reference(int idx) @@ -282,8 +219,8 @@ namespace RTLIL return index_; } - // The following is a helper key_compare class. Instead of for example nodict - // use nodict> if the order of cells in the + // The following is a helper key_compare class. Instead of for example pool + // use pool> if the order of cells in the // set has an influence on the algorithm. template struct compare_ptr_by_name { @@ -303,7 +240,7 @@ namespace RTLIL bool in(IdString rhs) { return *this == rhs; } bool in(const char *rhs) { return *this == rhs; } bool in(const std::string &rhs) { return *this == rhs; } - bool in(const nodict &rhs) { return rhs.count(*this) != 0; } + bool in(const pool &rhs) { return rhs.count(*this) != 0; } }; static inline std::string escape_id(std::string str) { @@ -470,8 +407,8 @@ namespace RTLIL return list_p->size(); } - operator nodict() const { - nodict result; + operator pool() const { + pool result; for (auto &it : *list_p) result.insert(it.second); return result; @@ -485,7 +422,7 @@ namespace RTLIL return result; } - nodict to_set() const { return *this; } + pool to_set() const { return *this; } std::vector to_vector() const { return *this; } }; }; @@ -619,7 +556,7 @@ public: SigSpec(RTLIL::SigBit bit, int width = 1); SigSpec(std::vector chunks); SigSpec(std::vector bits); - SigSpec(nodict bits); + SigSpec(pool bits); SigSpec(std::set bits); SigSpec(bool bit); @@ -676,15 +613,15 @@ public: void remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) const; void remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other); - void remove(const nodict &pattern); - void remove(const nodict &pattern, RTLIL::SigSpec *other) const; - void remove2(const nodict &pattern, RTLIL::SigSpec *other); + void remove(const pool &pattern); + void remove(const pool &pattern, RTLIL::SigSpec *other) const; + void remove2(const pool &pattern, RTLIL::SigSpec *other); void remove(int offset, int length = 1); void remove_const(); RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const; - RTLIL::SigSpec extract(const nodict &pattern, const RTLIL::SigSpec *other = NULL) const; + RTLIL::SigSpec extract(const pool &pattern, const RTLIL::SigSpec *other = NULL) const; RTLIL::SigSpec extract(int offset, int length = 1) const; void append(const RTLIL::SigSpec &signal); @@ -717,7 +654,7 @@ public: bool match(std::string pattern) const; std::set to_sigbit_set() const; - nodict to_sigbit_nodict() const; + pool to_sigbit_nodict() const; std::vector to_sigbit_vector() const; std::map to_sigbit_map(const RTLIL::SigSpec &other) const; dict to_sigbit_dict(const RTLIL::SigSpec &other) const; @@ -742,8 +679,8 @@ public: struct RTLIL::Selection { bool full_selection; - nodict selected_modules; - dict> selected_members; + pool selected_modules; + dict> selected_members; Selection(bool full = true) : full_selection(full) { } @@ -782,7 +719,7 @@ struct RTLIL::Monitor struct RTLIL::Design { - nodict monitors; + pool monitors; dict scratchpad; int refcount_modules_; @@ -869,7 +806,7 @@ protected: public: RTLIL::Design *design; - nodict monitors; + pool monitors; int refcount_wires_; int refcount_cells_; @@ -879,7 +816,7 @@ public: std::vector connections_; RTLIL::IdString name; - nodict avail_parameters; + pool avail_parameters; dict memories; dict processes; RTLIL_ATTRIBUTE_MEMBERS @@ -923,7 +860,7 @@ public: RTLIL::ObjRange cells() { return RTLIL::ObjRange(&cells_, &refcount_cells_); } // Removing wires is expensive. If you have to remove wires, remove them all at once. - void remove(const nodict &wires); + void remove(const pool &wires); void remove(RTLIL::Cell *cell); void rename(RTLIL::Wire *wire, RTLIL::IdString new_name); @@ -1313,35 +1250,4 @@ void RTLIL::Process::rewrite_sigspecs(T functor) YOSYS_NAMESPACE_END -inline size_t std::hash::operator()(const Yosys::RTLIL::IdString &arg) const { - return arg.index_; -} - -inline bool std::equal_to::operator()(const Yosys::RTLIL::IdString &lhs, const Yosys::RTLIL::IdString &rhs) const { - return lhs.index_ == rhs.index_; -} - -inline size_t std::hash::operator()(const Yosys::RTLIL::SigBit &arg) const { - if (arg.wire) { - size_t hash = arg.wire->name.index_; - hash = ((hash << 5) + hash) + arg.offset; - return hash; - } - return arg.data; -} - -inline bool std::equal_to::operator()(const Yosys::RTLIL::SigBit &lhs, const Yosys::RTLIL::SigBit &rhs) const { - if (lhs.wire || rhs.wire) - return lhs.wire == rhs.wire && lhs.offset == rhs.offset; - return lhs.data == rhs.data; -} - -inline size_t std::hash::operator()(const Yosys::RTLIL::SigSpec &arg) const { - return arg.get_hash(); -} - -inline bool std::equal_to::operator()(const Yosys::RTLIL::SigSpec &lhs, const Yosys::RTLIL::SigSpec &rhs) const { - return lhs == rhs; -} - #endif diff --git a/kernel/yosys.h b/kernel/yosys.h index 9b76d28c6..012b40c1f 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -124,7 +124,6 @@ YOSYS_NAMESPACE_BEGIN -#define nodict std::unordered_set #include "kernel/hashmap.h" using std::vector; diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc index d7edcfbfc..4c8f16f48 100644 --- a/passes/cmds/delete.cc +++ b/passes/cmds/delete.cc @@ -91,10 +91,10 @@ struct DeletePass : public Pass { continue; } - nodict delete_wires; - nodict delete_cells; - nodict delete_procs; - nodict delete_mems; + pool delete_wires; + pool delete_cells; + pool delete_procs; + pool delete_mems; for (auto &it : module->wires_) if (design->selected(module, it.second)) diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc index 6c24a8e5f..3b3fc208e 100644 --- a/passes/cmds/splitnets.cc +++ b/passes/cmds/splitnets.cc @@ -176,7 +176,7 @@ struct SplitnetsPass : public Pass { module->rewrite_sigspecs(worker); - nodict delete_wires; + pool delete_wires; for (auto &it : worker.splitmap) delete_wires.insert(it.first); module->remove(delete_wires); diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 01acb5c04..cb12b3922 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -262,7 +262,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } - nodict del_wires; + pool del_wires; int del_wires_count = 0; for (auto wire : maybe_del_wires) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index e8a38d212..1609a8be7 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -28,11 +28,11 @@ PRIVATE_NAMESPACE_BEGIN struct WreduceConfig { - nodict supported_cell_types; + pool supported_cell_types; WreduceConfig() { - supported_cell_types = nodict({ + supported_cell_types = pool({ "$not", "$pos", "$neg", "$and", "$or", "$xor", "$xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", From 6ce6689b639785f3d526c73faad6faba811beaf8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 26 Dec 2014 22:08:44 +0100 Subject: [PATCH 186/492] Using Yosys::dict and Yosys::pool in sigtools.h --- kernel/sigtools.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/kernel/sigtools.h b/kernel/sigtools.h index c3c6a8db1..5281b7a45 100644 --- a/kernel/sigtools.h +++ b/kernel/sigtools.h @@ -29,9 +29,10 @@ struct SigPool struct bitDef_t : public std::pair { bitDef_t() : std::pair(NULL, 0) { } bitDef_t(const RTLIL::SigBit &bit) : std::pair(bit.wire, bit.offset) { } + unsigned int hash() const { return first->name.hash() + second; } }; - std::set bits; + pool bits; void clear() { @@ -122,7 +123,7 @@ struct SigPool RTLIL::SigSpec export_all() { - std::set sig; + pool sig; for (auto &bit : bits) sig.insert(RTLIL::SigBit(bit.first, bit.second)); return sig; @@ -140,9 +141,10 @@ struct SigSet struct bitDef_t : public std::pair { bitDef_t() : std::pair(NULL, 0) { } bitDef_t(const RTLIL::SigBit &bit) : std::pair(bit.wire, bit.offset) { } + unsigned int hash() const { return first->name.hash() + second; } }; - std::map> bits; + dict> bits; void clear() { @@ -214,6 +216,7 @@ struct SigMap struct bitDef_t : public std::pair { bitDef_t() : std::pair(NULL, 0) { } bitDef_t(const RTLIL::SigBit &bit) : std::pair(bit.wire, bit.offset) { } + unsigned int hash() const { return first->name.hash() + second; } }; struct shared_bit_data_t { @@ -221,7 +224,7 @@ struct SigMap std::set bits; }; - std::map bits; + dict bits; SigMap(RTLIL::Module *module = NULL) { From 88d08e8f24cb2d43907a9d28d65fedc9638554ca Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 26 Dec 2014 23:21:23 +0100 Subject: [PATCH 187/492] Some cleanups in dict/pool hashtable implementation --- kernel/hashmap.h | 94 +++++++++++++++++------------------------------- 1 file changed, 33 insertions(+), 61 deletions(-) diff --git a/kernel/hashmap.h b/kernel/hashmap.h index 50098ac35..91df68a71 100644 --- a/kernel/hashmap.h +++ b/kernel/hashmap.h @@ -65,7 +65,7 @@ struct hash_cstr_ops { return true; } unsigned int hash(const char *a) const { - size_t hash = 5381; + unsigned int hash = 5381; while (*a) hash = mkhash(hash, *(a++)); return hash; @@ -81,6 +81,34 @@ struct hash_ptr_ops { } }; +inline int hashtable_size(int old_size) +{ + if (old_size < 53) return 53; + if (old_size < 113) return 113; + if (old_size < 251) return 251; + if (old_size < 503) return 503; + if (old_size < 1129) return 1129; + if (old_size < 2503) return 2503; + if (old_size < 5023) return 5023; + if (old_size < 11299) return 11299; + if (old_size < 25097) return 25097; + if (old_size < 50291) return 50291; + if (old_size < 112997) return 112997; + if (old_size < 251003) return 251003; + if (old_size < 503003) return 503003; + if (old_size < 1129991) return 1129991; + if (old_size < 2509993) return 2509993; + if (old_size < 5029991) return 5029991; + if (old_size < 11299997) return 11299997; + if (old_size < 25099999) return 25099999; + if (old_size < 50299999) return 50299999; + if (old_size < 113000009) return 113000009; + if (old_size < 250999999) return 250999999; + if (old_size < 503000009) return 503000009; + if (old_size < 1129999999) return 1129999999; + throw std::length_error("hash table exceeded maximum size"); +} + template> class dict { @@ -116,7 +144,7 @@ class dict entries.clear(); counter = other.size(); - int new_size = grow_size(counter); + int new_size = hashtable_size(counter); entries.reserve(new_size); for (auto &it : other) @@ -125,34 +153,6 @@ class dict rehash(); } - size_t grow_size(size_t old_size) - { - if (old_size < 53) return 53; - if (old_size < 113) return 113; - if (old_size < 251) return 251; - if (old_size < 503) return 503; - if (old_size < 1130) return 1130; - if (old_size < 2510) return 2510; - if (old_size < 5030) return 5030; - if (old_size < 11300) return 11300; - if (old_size < 25100) return 25100; - if (old_size < 50300) return 50300; - if (old_size < 113000) return 113000; - if (old_size < 251000) return 251000; - if (old_size < 503000) return 503000; - if (old_size < 1130000) return 1130000; - if (old_size < 2510000) return 2510000; - if (old_size < 5030000) return 5030000; - if (old_size < 11300000) return 11300000; - if (old_size < 25100000) return 25100000; - if (old_size < 50300000) return 50300000; - if (old_size < 113000000) return 113000000; - if (old_size < 251000000) return 251000000; - if (old_size < 503000000) return 503000000; - if (old_size < 1130000000) return 1130000000; - throw std::length_error("maximum size for dict reached"); - } - int mkhash(const K &key) const { unsigned int hash = 0; @@ -221,7 +221,7 @@ class dict if (free_list < 0) { int i = entries.size(); - entries.resize(grow_size(i)); + entries.resize(hashtable_size(i)); entries[i].udata = value; entries[i].set_next_used(0); counter++; @@ -473,7 +473,7 @@ class pool entries.clear(); counter = other.size(); - int new_size = grow_size(counter); + int new_size = hashtable_size(counter); entries.reserve(new_size); for (auto &it : other) @@ -482,34 +482,6 @@ class pool rehash(); } - size_t grow_size(size_t old_size) - { - if (old_size < 53) return 53; - if (old_size < 113) return 113; - if (old_size < 251) return 251; - if (old_size < 503) return 503; - if (old_size < 1130) return 1130; - if (old_size < 2510) return 2510; - if (old_size < 5030) return 5030; - if (old_size < 11300) return 11300; - if (old_size < 25100) return 25100; - if (old_size < 50300) return 50300; - if (old_size < 113000) return 113000; - if (old_size < 251000) return 251000; - if (old_size < 503000) return 503000; - if (old_size < 1130000) return 1130000; - if (old_size < 2510000) return 2510000; - if (old_size < 5030000) return 5030000; - if (old_size < 11300000) return 11300000; - if (old_size < 25100000) return 25100000; - if (old_size < 50300000) return 50300000; - if (old_size < 113000000) return 113000000; - if (old_size < 251000000) return 251000000; - if (old_size < 503000000) return 503000000; - if (old_size < 1130000000) return 1130000000; - throw std::length_error("maximum size for pool reached"); - } - int mkhash(const K &key) const { unsigned int hash = 0; @@ -578,7 +550,7 @@ class pool if (free_list < 0) { int i = entries.size(); - entries.resize(grow_size(i)); + entries.resize(hashtable_size(i)); entries[i].key = key; entries[i].set_next_used(0); counter++; From 66ab88d7b0636c21d5df74f753ed379a799fd783 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 27 Dec 2014 03:04:50 +0100 Subject: [PATCH 188/492] More hashtable finetuning --- kernel/hashmap.h | 31 +++++++++++++++++++++++++------ kernel/rtlil.cc | 4 ++-- kernel/rtlil.h | 8 +++++--- kernel/yosys.h | 3 ++- passes/cmds/delete.cc | 4 ++-- passes/cmds/splitnets.cc | 2 +- passes/opt/opt_clean.cc | 2 +- passes/opt/opt_const.cc | 2 +- passes/opt/opt_share.cc | 2 +- 9 files changed, 40 insertions(+), 18 deletions(-) diff --git a/kernel/hashmap.h b/kernel/hashmap.h index 91df68a71..729b4916c 100644 --- a/kernel/hashmap.h +++ b/kernel/hashmap.h @@ -23,6 +23,8 @@ #include #include +#define YOSYS_HASHTABLE_SIZE_FACTOR 3 + inline unsigned int mkhash(unsigned int a, unsigned int b) { return ((a << 5) + a) ^ b; } @@ -81,8 +83,19 @@ struct hash_ptr_ops { } }; +struct hash_obj_ops { + bool cmp(const void *a, const void *b) const { + return a == b; + } + template + unsigned int hash(const T *a) const { + return a->name.hash(); + } +}; + inline int hashtable_size(int old_size) { + // prime numbers, approx. in powers of two if (old_size < 53) return 53; if (old_size < 113) return 113; if (old_size < 251) return 251; @@ -144,7 +157,9 @@ class dict entries.clear(); counter = other.size(); - int new_size = hashtable_size(counter); + int new_size = hashtable_size(YOSYS_HASHTABLE_SIZE_FACTOR * counter); + hashtable.resize(new_size); + new_size = new_size / YOSYS_HASHTABLE_SIZE_FACTOR + 1; entries.reserve(new_size); for (auto &it : other) @@ -165,7 +180,6 @@ class dict { free_list = -1; - hashtable.resize(entries.size()); for (auto &h : hashtable) h = -1; @@ -221,7 +235,9 @@ class dict if (free_list < 0) { int i = entries.size(); - entries.resize(hashtable_size(i)); + int new_size = hashtable_size(YOSYS_HASHTABLE_SIZE_FACTOR * entries.size()); + hashtable.resize(new_size); + entries.resize(new_size / YOSYS_HASHTABLE_SIZE_FACTOR + 1); entries[i].udata = value; entries[i].set_next_used(0); counter++; @@ -473,7 +489,9 @@ class pool entries.clear(); counter = other.size(); - int new_size = hashtable_size(counter); + int new_size = hashtable_size(YOSYS_HASHTABLE_SIZE_FACTOR * counter); + hashtable.resize(new_size); + new_size = new_size / YOSYS_HASHTABLE_SIZE_FACTOR + 1; entries.reserve(new_size); for (auto &it : other) @@ -494,7 +512,6 @@ class pool { free_list = -1; - hashtable.resize(entries.size()); for (auto &h : hashtable) h = -1; @@ -550,7 +567,9 @@ class pool if (free_list < 0) { int i = entries.size(); - entries.resize(hashtable_size(i)); + int new_size = hashtable_size(YOSYS_HASHTABLE_SIZE_FACTOR * entries.size()); + hashtable.resize(new_size); + entries.resize(new_size / YOSYS_HASHTABLE_SIZE_FACTOR + 1); entries[i].key = key; entries[i].set_next_used(0); counter++; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 8f65f5273..0114cbd60 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1132,7 +1132,7 @@ namespace { struct DeleteWireWorker { RTLIL::Module *module; - const pool *wires_p; + const pool *wires_p; void operator()(RTLIL::SigSpec &sig) { std::vector chunks = sig; @@ -1146,7 +1146,7 @@ namespace { }; } -void RTLIL::Module::remove(const pool &wires) +void RTLIL::Module::remove(const pool &wires) { log_assert(refcount_wires_ == 0); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index ae37c350c..c50a58619 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -708,6 +708,8 @@ struct RTLIL::Selection struct RTLIL::Monitor { + RTLIL::IdString name; + Monitor() { name = stringf("$%d", autoidx++); } virtual ~Monitor() { } virtual void notify_module_add(RTLIL::Module*) { } virtual void notify_module_del(RTLIL::Module*) { } @@ -719,7 +721,7 @@ struct RTLIL::Monitor struct RTLIL::Design { - pool monitors; + pool monitors; dict scratchpad; int refcount_modules_; @@ -806,7 +808,7 @@ protected: public: RTLIL::Design *design; - pool monitors; + pool monitors; int refcount_wires_; int refcount_cells_; @@ -860,7 +862,7 @@ public: RTLIL::ObjRange cells() { return RTLIL::ObjRange(&cells_, &refcount_cells_); } // Removing wires is expensive. If you have to remove wires, remove them all at once. - void remove(const pool &wires); + void remove(const pool &wires); void remove(RTLIL::Cell *cell); void rename(RTLIL::Wire *wire, RTLIL::IdString new_name); diff --git a/kernel/yosys.h b/kernel/yosys.h index 012b40c1f..d47f3a958 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -149,6 +149,8 @@ void remove_directory(std::string dirname); template int GetSize(const T &obj) { return obj.size(); } int GetSize(RTLIL::Wire *wire); +extern int autoidx; + YOSYS_NAMESPACE_END #include "kernel/log.h" @@ -164,7 +166,6 @@ void yosys_shutdown(); Tcl_Interp *yosys_get_tcl_interp(); #endif -extern int autoidx; extern RTLIL::Design *yosys_design; RTLIL::IdString new_id(std::string file, int line, std::string func); diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc index 4c8f16f48..5bf2a36b8 100644 --- a/passes/cmds/delete.cc +++ b/passes/cmds/delete.cc @@ -91,8 +91,8 @@ struct DeletePass : public Pass { continue; } - pool delete_wires; - pool delete_cells; + pool delete_wires; + pool delete_cells; pool delete_procs; pool delete_mems; diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc index 3b3fc208e..2523c1660 100644 --- a/passes/cmds/splitnets.cc +++ b/passes/cmds/splitnets.cc @@ -176,7 +176,7 @@ struct SplitnetsPass : public Pass { module->rewrite_sigspecs(worker); - pool delete_wires; + pool delete_wires; for (auto &it : worker.splitmap) delete_wires.insert(it.first); module->remove(delete_wires); diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index cb12b3922..b387e0381 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -262,7 +262,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } - pool del_wires; + pool del_wires; int del_wires_count = 0; for (auto wire : maybe_del_wires) diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc index 9c1a18782..f78ea6cc3 100644 --- a/passes/opt/opt_const.cc +++ b/passes/opt/opt_const.cc @@ -199,7 +199,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons dict invert_map; TopoSort> cells; - dict, hash_ptr_ops> cell_to_inbit; + dict, hash_obj_ops> cell_to_inbit; dict> outbit_to_cell; for (auto cell : module->cells()) diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index 9bc308873..91bfd58ab 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -41,7 +41,7 @@ struct OptShareWorker CellTypes ct; int total_count; #ifdef USE_CELL_HASH_CACHE - dict cell_hash_cache; + dict cell_hash_cache; #endif #ifdef USE_CELL_HASH_CACHE From 12ca6538a4e429ef318f47b5bb07f6a2a8dd2538 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 27 Dec 2014 03:26:30 +0100 Subject: [PATCH 189/492] Fixed mem2reg warning message --- frontends/ast/simplify.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index a78fafbd1..b76701943 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -102,13 +102,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, verbose_activate: if (mem2reg_set.count(mem) == 0) { - log_warning("Replacing memory %s with list of registers.", mem->str.c_str()); + std::string message = stringf("Replacing memory %s with list of registers.", mem->str.c_str()); bool first_element = true; for (auto &place : mem2reg_places[it.first]) { - log("%s%s", first_element ? " See " : ", ", place.c_str()); + message += stringf("%s%s", first_element ? " See " : ", ", place.c_str()); first_element = false; } - log("\n"); + log_warning("%s\n", message.c_str()); } silent_activate: From 7751c491fb08eccb13f2b5f5609d3fd6d2a8ffef Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 27 Dec 2014 03:40:27 +0100 Subject: [PATCH 190/492] Improved some warning messages --- frontends/verilog/verilog_lexer.l | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 74a66d964..42b5bf7ea 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -254,8 +254,12 @@ supply1 { return TOK_SUPPLY1; } } "/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" { - log_warning("Found one of those horrible `(synopsys|synthesis) translate_off' comments.\n" - "It is strongly suggested to use `ifdef constructs instead!\n"); + static bool printed_warning = false; + if (!printed_warning) { + log_warning("Found one of those horrible `(synopsys|synthesis) translate_off' comments.\n" + "Yosys does support them but it is recommended to use `ifdef constructs instead!\n"); + printed_warning = true; + } BEGIN(SYNOPSYS_TRANSLATE_OFF); } . /* ignore synopsys translate_off body */ @@ -266,13 +270,21 @@ supply1 { return TOK_SUPPLY1; } BEGIN(SYNOPSYS_FLAGS); } full_case { - log_warning("Found one of those horrible `(synopsys|synthesis) full_case' comments.\n" - "It is strongly suggested to use verilog x-values and default branches instead!\n"); + static bool printed_warning = false; + if (!printed_warning) { + log_warning("Found one of those horrible `(synopsys|synthesis) full_case' comments.\n" + "Yosys does support them but it is recommended to use verilog `full_case' attributes instead!\n"); + printed_warning = true; + } return TOK_SYNOPSYS_FULL_CASE; } parallel_case { - log_warning("Found one of those horrible `(synopsys|synthesis) parallel_case' comments.\n" - "It is strongly suggested to use verilog `parallel_case' attributes instead!\n"); + static bool printed_warning = false; + if (!printed_warning) { + log_warning("Found one of those horrible `(synopsys|synthesis) parallel_case' comments.\n" + "Yosys does support them but it is recommended to use verilog `parallel_case' attributes instead!\n"); + printed_warning = true; + } return TOK_SYNOPSYS_PARALLEL_CASE; } . /* ignore everything else */ From d6ee6f653fa795efcea910fd4ad4bc6ee09a4784 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 27 Dec 2014 11:01:59 +0100 Subject: [PATCH 191/492] Better help message printing for command line tool --- kernel/driver.cc | 149 ++++++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 72 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index 6ba0c1134..90f479307 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -92,6 +92,82 @@ int main(int argc, char **argv) } #endif + if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "-help") || !strcmp(argv[1], "--help"))) + { + printf("\n"); + printf("Usage: %s [options] [ [..]]\n", argv[0]); + printf("\n"); + printf(" -Q\n"); + printf(" suppress printing of banner (copyright, disclaimer, version)\n"); + printf("\n"); + printf(" -T\n"); + printf(" suppress printing of footer (log hash, version, timing statistics)\n"); + printf("\n"); + printf(" -q\n"); + printf(" quiet operation. only write warnings and error messages to console\n"); + printf(" use this option twice to also quiet warning messages\n"); + printf("\n"); + printf(" -v \n"); + printf(" print log headers up to level to the console. (implies -q)\n"); + printf("\n"); + printf(" -t\n"); + printf(" annotate all log messages with a time stamp\n"); + printf("\n"); + printf(" -d\n"); + printf(" print more detailed timing stats at exit\n"); + printf("\n"); + printf(" -l logfile\n"); + printf(" write log messages to the specified file\n"); + printf("\n"); + printf(" -o outfile\n"); + printf(" write the design to the specified file on exit\n"); + printf("\n"); + printf(" -b backend\n"); + printf(" use this backend for the output file specified on the command line\n"); + printf("\n"); + printf(" -f backend\n"); + printf(" use the specified front for the input files on the command line\n"); + printf("\n"); + printf(" -H\n"); + printf(" print the command list\n"); + printf("\n"); + printf(" -h command\n"); + printf(" print the help message for the specified command\n"); + printf("\n"); + printf(" -s scriptfile\n"); + printf(" execute the commands in the script file\n"); + printf("\n"); + printf(" -c tcl_scriptfile\n"); + printf(" execute the commands in the tcl script file (see 'help tcl' for details)\n"); + printf("\n"); + printf(" -p command\n"); + printf(" execute the commands\n"); + printf("\n"); + printf(" -m module_file\n"); + printf(" load the specified module (aka plugin)\n"); + printf("\n"); + printf(" -A\n"); + printf(" will call abort() at the end of the script. useful for debugging\n"); + printf("\n"); + printf(" -V\n"); + printf(" print version information and exit\n"); + printf("\n"); + printf("The option -S is an shortcut for calling the \"synth\" command, a default\n"); + printf("script for transforming the verilog input to a gate-level netlist. For example:\n"); + printf("\n"); + printf(" yosys -o output.blif -S input.v\n"); + printf("\n"); + printf("For more complex synthesis jobs it is recommended to use the read_* and write_*\n"); + printf("commands in a script file instead of specifying input and output files on the\n"); + printf("command line.\n"); + printf("\n"); + printf("When no commands, script files or input files are specified on the command\n"); + printf("line, yosys automatically enters the interactive command mode. Use the 'help'\n"); + printf("command to get information on the individual commands.\n"); + printf("\n"); + exit(0); + } + int opt; while ((opt = getopt(argc, argv, "AQTVSm:f:Hh:b:o:p:l:qv:tds:c:")) != -1) { @@ -165,78 +241,7 @@ int main(int argc, char **argv) scriptfile_tcl = true; break; default: - fprintf(stderr, "\n"); - fprintf(stderr, "Usage: %s [-V -S -Q -T -q] [-v [-t] [-l ] [-o ] [-f ] [-h cmd] \\\n", argv[0]); - fprintf(stderr, " %*s[{-s|-c} ] [-p [-p ..]] [-b ] [-m ] [ [..]]\n", int(strlen(argv[0])+1), ""); - fprintf(stderr, "\n"); - fprintf(stderr, " -Q\n"); - fprintf(stderr, " suppress printing of banner (copyright, disclaimer, version)\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -T\n"); - fprintf(stderr, " suppress printing of footer (log hash, version, timing statistics)\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -q\n"); - fprintf(stderr, " quiet operation. only write warnings and error messages to console\n"); - fprintf(stderr, " use this option twice to also quiet warning messages\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -v \n"); - fprintf(stderr, " print log headers up to level to the console. (implies -q)\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -t\n"); - fprintf(stderr, " annotate all log messages with a time stamp\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -d\n"); - fprintf(stderr, " print more detailed timing stats at exit\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -l logfile\n"); - fprintf(stderr, " write log messages to the specified file\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -o outfile\n"); - fprintf(stderr, " write the design to the specified file on exit\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -b backend\n"); - fprintf(stderr, " use this backend for the output file specified on the command line\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -f backend\n"); - fprintf(stderr, " use the specified front for the input files on the command line\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -H\n"); - fprintf(stderr, " print the command list\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -h command\n"); - fprintf(stderr, " print the help message for the specified command\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -s scriptfile\n"); - fprintf(stderr, " execute the commands in the script file\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -c tcl_scriptfile\n"); - fprintf(stderr, " execute the commands in the tcl script file (see 'help tcl' for details)\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -p command\n"); - fprintf(stderr, " execute the commands\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -m module_file\n"); - fprintf(stderr, " load the specified module (aka plugin)\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -A\n"); - fprintf(stderr, " will call abort() at the end of the script. useful for debugging\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " -V\n"); - fprintf(stderr, " print version information and exit\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "The option -S is an shortcut for calling the \"synth\" command, a default\n"); - fprintf(stderr, "script for transforming the verilog input to a gate-level netlist. For example:\n"); - fprintf(stderr, "\n"); - fprintf(stderr, " yosys -o output.blif -S input.v\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "For more complex synthesis jobs it is recommended to use the read_* and write_*\n"); - fprintf(stderr, "commands in a script file instead of specifying input and output files on the\n"); - fprintf(stderr, "command line.\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "When no commands, script files or input files are specified on the command\n"); - fprintf(stderr, "line, yosys automatically enters the interactive command mode. Use the 'help'\n"); - fprintf(stderr, "command to get information on the individual commands.\n"); - fprintf(stderr, "\n"); + fprintf(stderr, "Run '%s -h' for help.\n", argv[0]); exit(1); } } From 2c2f8e6e9f4eadbb191df8a8dbeee95443fc9f08 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 27 Dec 2014 11:25:51 +0100 Subject: [PATCH 192/492] Added memory statistics (at least on linux) --- kernel/driver.cc | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index 90f479307..4700bf61b 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -30,6 +30,11 @@ #include #include +#ifdef __linux__ +# include +# include +#endif + #if !defined(_WIN32) || defined(__MINGW32__) # include #else @@ -320,11 +325,26 @@ int main(int argc, char **argv) #ifdef _WIN32 log("End of script. Logfile hash: %s\n", hash.c_str()); #else + std::string meminfo; + std::string stats_divider = ", "; +# ifdef __linux__ + std::ifstream statm; + statm.open(stringf("/proc/%lld/statm", (long long)getpid())); + if (statm.is_open()) { + int sz_total, sz_resident; + statm >> sz_total >> sz_resident; + meminfo = stringf(", MEM: %.2f MB total, %.2f MB resident", + sz_total * (getpagesize() / 1024.0 / 1024.0), + sz_resident * (getpagesize() / 1024.0 / 1024.0)); + stats_divider = "\n"; + } +# endif + struct rusage ru_buffer; getrusage(RUSAGE_SELF, &ru_buffer); - log("End of script. Logfile hash: %s, CPU: user %.2fs system %.2fs\n", hash.c_str(), - ru_buffer.ru_utime.tv_sec + 1e-6 * ru_buffer.ru_utime.tv_usec, - ru_buffer.ru_stime.tv_sec + 1e-6 * ru_buffer.ru_stime.tv_usec); + log("End of script. Logfile hash: %s%sCPU: user %.2fs system %.2fs%s\n", hash.c_str(), + stats_divider.c_str(), ru_buffer.ru_utime.tv_sec + 1e-6 * ru_buffer.ru_utime.tv_usec, + ru_buffer.ru_stime.tv_sec + 1e-6 * ru_buffer.ru_stime.tv_usec, meminfo.c_str()); #endif log("%s\n", yosys_version_str); From 6c8b0a5fd138d19b47191400f020c2472944f826 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 27 Dec 2014 12:02:57 +0100 Subject: [PATCH 193/492] More dict/pool related changes --- kernel/hashmap.h | 8 ++++ kernel/modtools.h | 81 +++++++++++++++++++++-------------- kernel/rtlil.cc | 16 +++---- kernel/rtlil.h | 4 +- passes/memory/memory_share.cc | 4 +- passes/opt/share.cc | 18 ++++---- 6 files changed, 77 insertions(+), 54 deletions(-) diff --git a/kernel/hashmap.h b/kernel/hashmap.h index 729b4916c..431e8122e 100644 --- a/kernel/hashmap.h +++ b/kernel/hashmap.h @@ -25,10 +25,18 @@ #define YOSYS_HASHTABLE_SIZE_FACTOR 3 +// The XOR version of DJB2 +// (traditionally 5381 is used as starting value for the djb2 hash) inline unsigned int mkhash(unsigned int a, unsigned int b) { return ((a << 5) + a) ^ b; } +// The ADD version of DJB2 +// (use this version as last call for cache locality in b) +inline unsigned int mkhash_add(unsigned int a, unsigned int b) { + return ((a << 5) + a) + b; +} + template struct hash_ops { bool cmp(const T &a, const T &b) const { return a == b; diff --git a/kernel/modtools.h b/kernel/modtools.h index e3020ae3c..439699eaf 100644 --- a/kernel/modtools.h +++ b/kernel/modtools.h @@ -33,6 +33,7 @@ struct ModIndex : public RTLIL::Monitor RTLIL::IdString port; int offset; + PortInfo() : cell(), port(), offset() { } PortInfo(RTLIL::Cell* _c, RTLIL::IdString _p, int _o) : cell(_c), port(_p), offset(_o) { } bool operator<(const PortInfo &other) const { @@ -42,19 +43,27 @@ struct ModIndex : public RTLIL::Monitor return offset < other.offset; return port < other.port; } + + bool operator==(const PortInfo &other) const { + return cell == other.cell && port == other.port && offset == other.offset; + } + + unsigned int hash() const { + return mkhash_add(mkhash(cell->name.hash(), port.hash()), offset); + } }; struct SigBitInfo { bool is_input, is_output; - std::set ports; + pool ports; SigBitInfo() : is_input(false), is_output(false) { } }; SigMap sigmap; RTLIL::Module *module; - std::map database; + dict database; bool auto_reload_module; void port_add(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &sig) @@ -168,9 +177,9 @@ struct ModIndex : public RTLIL::Monitor return info->is_output; } - std::set &query_ports(RTLIL::SigBit bit) + pool &query_ports(RTLIL::SigBit bit) { - static std::set empty_result_set; + static pool empty_result_set; SigBitInfo *info = query(bit); if (info == nullptr) return empty_result_set; @@ -193,6 +202,14 @@ struct ModWalker return port < other.port; return offset < other.offset; } + + bool operator==(const PortBit &other) const { + return cell == other.cell && port == other.port && offset == other.offset; + } + + unsigned int hash() const { + return mkhash_add(mkhash(cell->name.hash(), port.hash()), offset); + } }; RTLIL::Design *design; @@ -201,11 +218,11 @@ struct ModWalker CellTypes ct; SigMap sigmap; - std::map> signal_drivers; - std::map> signal_consumers; - std::set signal_inputs, signal_outputs; + dict> signal_drivers; + dict> signal_consumers; + pool signal_inputs, signal_outputs; - std::map> cell_outputs, cell_inputs; + dict, hash_obj_ops> cell_outputs, cell_inputs; void add_wire(RTLIL::Wire *wire) { @@ -286,11 +303,11 @@ struct ModWalker // get_* methods -- single RTLIL::SigBit template - inline bool get_drivers(std::set &result, RTLIL::SigBit bit) const + inline bool get_drivers(pool &result, RTLIL::SigBit bit) const { bool found = false; if (signal_drivers.count(bit)) { - const std::set &r = signal_drivers.at(bit); + const pool &r = signal_drivers.at(bit); result.insert(r.begin(), r.end()); found = true; } @@ -298,11 +315,11 @@ struct ModWalker } template - inline bool get_consumers(std::set &result, RTLIL::SigBit bit) const + inline bool get_consumers(pool &result, RTLIL::SigBit bit) const { bool found = false; if (signal_consumers.count(bit)) { - const std::set &r = signal_consumers.at(bit); + const pool &r = signal_consumers.at(bit); result.insert(r.begin(), r.end()); found = true; } @@ -310,7 +327,7 @@ struct ModWalker } template - inline bool get_inputs(std::set &result, RTLIL::SigBit bit) const + inline bool get_inputs(pool &result, RTLIL::SigBit bit) const { bool found = false; if (signal_inputs.count(bit)) @@ -319,7 +336,7 @@ struct ModWalker } template - inline bool get_outputs(std::set &result, RTLIL::SigBit bit) const + inline bool get_outputs(pool &result, RTLIL::SigBit bit) const { bool found = false; if (signal_outputs.count(bit)) @@ -330,12 +347,12 @@ struct ModWalker // get_* methods -- container of RTLIL::SigBit's (always by reference) template - inline bool get_drivers(std::set &result, const T &bits) const + inline bool get_drivers(pool &result, const T &bits) const { bool found = false; for (RTLIL::SigBit bit : bits) if (signal_drivers.count(bit)) { - const std::set &r = signal_drivers.at(bit); + const pool &r = signal_drivers.at(bit); result.insert(r.begin(), r.end()); found = true; } @@ -343,12 +360,12 @@ struct ModWalker } template - inline bool get_consumers(std::set &result, const T &bits) const + inline bool get_consumers(pool &result, const T &bits) const { bool found = false; for (RTLIL::SigBit bit : bits) if (signal_consumers.count(bit)) { - const std::set &r = signal_consumers.at(bit); + const pool &r = signal_consumers.at(bit); result.insert(r.begin(), r.end()); found = true; } @@ -356,7 +373,7 @@ struct ModWalker } template - inline bool get_inputs(std::set &result, const T &bits) const + inline bool get_inputs(pool &result, const T &bits) const { bool found = false; for (RTLIL::SigBit bit : bits) @@ -366,7 +383,7 @@ struct ModWalker } template - inline bool get_outputs(std::set &result, const T &bits) const + inline bool get_outputs(pool &result, const T &bits) const { bool found = false; for (RTLIL::SigBit bit : bits) @@ -377,25 +394,25 @@ struct ModWalker // get_* methods -- call by RTLIL::SigSpec (always by value) - bool get_drivers(std::set &result, RTLIL::SigSpec signal) const + bool get_drivers(pool &result, RTLIL::SigSpec signal) const { std::vector bits = sigmap(signal); return get_drivers(result, bits); } - bool get_consumers(std::set &result, RTLIL::SigSpec signal) const + bool get_consumers(pool &result, RTLIL::SigSpec signal) const { std::vector bits = sigmap(signal); return get_consumers(result, bits); } - bool get_inputs(std::set &result, RTLIL::SigSpec signal) const + bool get_inputs(pool &result, RTLIL::SigSpec signal) const { std::vector bits = sigmap(signal); return get_inputs(result, bits); } - bool get_outputs(std::set &result, RTLIL::SigSpec signal) const + bool get_outputs(pool &result, RTLIL::SigSpec signal) const { std::vector bits = sigmap(signal); return get_outputs(result, bits); @@ -405,47 +422,47 @@ struct ModWalker template inline bool has_drivers(const T &sig) const { - std::set result; + pool result; return get_drivers(result, sig); } template inline bool has_consumers(const T &sig) const { - std::set result; + pool result; return get_consumers(result, sig); } template inline bool has_inputs(const T &sig) const { - std::set result; + pool result; return get_inputs(result, sig); } template inline bool has_outputs(const T &sig) const { - std::set result; + pool result; return get_outputs(result, sig); } // has_* methods -- call by value inline bool has_drivers(RTLIL::SigSpec sig) const { - std::set result; + pool result; return get_drivers(result, sig); } inline bool has_consumers(RTLIL::SigSpec sig) const { - std::set result; + pool result; return get_consumers(result, sig); } inline bool has_inputs(RTLIL::SigSpec sig) const { - std::set result; + pool result; return get_inputs(result, sig); } inline bool has_outputs(RTLIL::SigSpec sig) const { - std::set result; + pool result; return get_outputs(result, sig); } }; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 0114cbd60..23edcceef 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2256,8 +2256,6 @@ void RTLIL::SigSpec::unpack() const that->hash_ = 0; } -#define DJB2(_hash, _value) (_hash) = (((_hash) << 5) + (_hash)) + (_value) - void RTLIL::SigSpec::updhash() const { RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; @@ -2272,11 +2270,11 @@ void RTLIL::SigSpec::updhash() const for (auto &c : that->chunks_) if (c.wire == NULL) { for (auto &v : c.data) - DJB2(that->hash_, v); + that->hash_ = mkhash(that->hash_, v); } else { - DJB2(that->hash_, c.wire->name.index_); - DJB2(that->hash_, c.offset); - DJB2(that->hash_, c.width); + that->hash_ = mkhash(that->hash_, c.wire->name.index_); + that->hash_ = mkhash(that->hash_, c.offset); + that->hash_ = mkhash(that->hash_, c.width); } if (that->hash_ == 0) @@ -2378,7 +2376,7 @@ void RTLIL::SigSpec::remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other void RTLIL::SigSpec::remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) { - pool pattern_bits = pattern.to_sigbit_nodict(); + pool pattern_bits = pattern.to_sigbit_pool(); remove2(pattern_bits, other); } @@ -2439,7 +2437,7 @@ void RTLIL::SigSpec::remove2(const pool &pattern, RTLIL::SigSpec RTLIL::SigSpec RTLIL::SigSpec::extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other) const { - pool pattern_bits = pattern.to_sigbit_nodict(); + pool pattern_bits = pattern.to_sigbit_pool(); return extract(pattern_bits, other); } @@ -2943,7 +2941,7 @@ std::set RTLIL::SigSpec::to_sigbit_set() const return sigbits; } -pool RTLIL::SigSpec::to_sigbit_nodict() const +pool RTLIL::SigSpec::to_sigbit_pool() const { cover("kernel.rtlil.sigspec.to_sigbit_pool"); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index c50a58619..cb654c3af 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -654,7 +654,7 @@ public: bool match(std::string pattern) const; std::set to_sigbit_set() const; - pool to_sigbit_nodict() const; + pool to_sigbit_pool() const; std::vector to_sigbit_vector() const; std::map to_sigbit_map(const RTLIL::SigSpec &other) const; dict to_sigbit_dict(const RTLIL::SigSpec &other) const; @@ -1176,7 +1176,7 @@ inline bool RTLIL::SigBit::operator!=(const RTLIL::SigBit &other) const { inline unsigned int RTLIL::SigBit::hash() const { if (wire) - return wire->name.hash() * 33 + offset; + return mkhash_add(wire->name.hash(), offset); return data; } diff --git a/passes/memory/memory_share.cc b/passes/memory/memory_share.cc index f77b304b4..ec8df7598 100644 --- a/passes/memory/memory_share.cc +++ b/passes/memory/memory_share.cc @@ -560,13 +560,13 @@ struct MemoryShareWorker while (!bits_queue.empty()) { - std::set portbits; + pool portbits; modwalker.get_drivers(portbits, bits_queue); bits_queue.clear(); for (auto &pbit : portbits) if (sat_cells.count(pbit.cell) == 0 && cone_ct.cell_known(pbit.cell->type)) { - std::set &cell_inputs = modwalker.cell_inputs[pbit.cell]; + pool &cell_inputs = modwalker.cell_inputs[pbit.cell]; bits_queue.insert(cell_inputs.begin(), cell_inputs.end()); sat_cells.insert(pbit.cell); } diff --git a/passes/opt/share.cc b/passes/opt/share.cc index cb7510553..41a4a6908 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -75,7 +75,7 @@ struct ShareWorker for (auto &it : module->cells_) if (!fwd_ct.cell_known(it.second->type)) { - std::set &bits = modwalker.cell_inputs[it.second]; + pool &bits = modwalker.cell_inputs[it.second]; queue_bits.insert(bits.begin(), bits.end()); } @@ -83,19 +83,19 @@ struct ShareWorker while (!queue_bits.empty()) { - std::set portbits; + pool portbits; modwalker.get_drivers(portbits, queue_bits); queue_bits.clear(); for (auto &pbit : portbits) { if (pbit.cell->type == "$mux" || pbit.cell->type == "$pmux") { - std::set bits = modwalker.sigmap(pbit.cell->getPort("\\S")).to_sigbit_set(); + pool bits = modwalker.sigmap(pbit.cell->getPort("\\S")).to_sigbit_pool(); terminal_bits.insert(bits.begin(), bits.end()); queue_bits.insert(bits.begin(), bits.end()); visited_cells.insert(pbit.cell); } if (fwd_ct.cell_known(pbit.cell->type) && visited_cells.count(pbit.cell) == 0) { - std::set &bits = modwalker.cell_inputs[pbit.cell]; + pool &bits = modwalker.cell_inputs[pbit.cell]; terminal_bits.insert(bits.begin(), bits.end()); queue_bits.insert(bits.begin(), bits.end()); visited_cells.insert(pbit.cell); @@ -730,8 +730,8 @@ struct ShareWorker if (forbidden_controls_cache.count(cell)) return forbidden_controls_cache.at(cell); - std::set pbits; - std::set consumer_cells; + pool pbits; + pool consumer_cells; modwalker.get_consumers(pbits, modwalker.cell_outputs[cell]); @@ -802,8 +802,8 @@ struct ShareWorker if (activation_patterns_cache.count(cell)) return activation_patterns_cache.at(cell); - const std::set &cell_out_bits = modwalker.cell_outputs[cell]; - std::set driven_cells, driven_data_muxes; + const pool &cell_out_bits = modwalker.cell_outputs[cell]; + pool driven_cells, driven_data_muxes; for (auto &bit : cell_out_bits) { @@ -1196,7 +1196,7 @@ struct ShareWorker while (!bits_queue.empty()) { - std::set portbits; + pool portbits; modwalker.get_drivers(portbits, bits_queue); bits_queue.clear(); From 3e8e483233321d7efadbb78ba746a7797c102a3a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 27 Dec 2014 13:04:44 +0100 Subject: [PATCH 194/492] Various improvements in ModIndex --- kernel/modtools.h | 66 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/kernel/modtools.h b/kernel/modtools.h index 439699eaf..56362dbc8 100644 --- a/kernel/modtools.h +++ b/kernel/modtools.h @@ -59,6 +59,13 @@ struct ModIndex : public RTLIL::Monitor pool ports; SigBitInfo() : is_input(false), is_output(false) { } + + void merge(const SigBitInfo &other) + { + is_input = is_input || other.is_input; + is_output = is_output || other.is_output; + ports.insert(other.ports.begin(), other.ports.end()); + } }; SigMap sigmap; @@ -109,30 +116,71 @@ struct ModIndex : public RTLIL::Monitor port_add(cell, conn.first, conn.second); auto_reload_module = false; + // log("Auto-reload in ModIndex -- possible performance bug!\n"); } virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) YS_OVERRIDE { + log_assert(module == cell->module); + if (auto_reload_module) - reload_module(); + return; port_del(cell, port, old_sig); port_add(cell, port, sig); } - virtual void notify_connect(RTLIL::Module *mod, const RTLIL::SigSig&) + virtual void notify_connect(RTLIL::Module *mod, const RTLIL::SigSig &sigsig) YS_OVERRIDE + { + log_assert(module == mod); + + if (auto_reload_module) + return; + + for (int i = 0; i < GetSize(sigsig.first); i++) + { + RTLIL::SigBit lhs = sigmap(sigsig.first[i]); + RTLIL::SigBit rhs = sigmap(sigsig.second[i]); + bool has_lhs = database.count(lhs); + bool has_rhs = database.count(rhs); + + if (!has_lhs && !has_rhs) { + sigmap.add(lhs, rhs); + } else + if (!has_rhs) { + SigBitInfo new_info = database.at(lhs); + database.erase(lhs); + sigmap.add(lhs, rhs); + database[sigmap(lhs)] = new_info; + } else + if (!has_lhs) { + SigBitInfo new_info = database.at(rhs); + database.erase(rhs); + sigmap.add(lhs, rhs); + database[sigmap(rhs)] = new_info; + } else { + #if 1 + auto_reload_module = true; + return; + #else + SigBitInfo new_info = database.at(lhs); + new_info.merge(database.at(rhs)); + database.erase(lhs); + database.erase(rhs); + sigmap.add(lhs, rhs); + database[sigmap(rhs)] = new_info; + #endif + } + } + } + + virtual void notify_connect(RTLIL::Module *mod, const std::vector&) YS_OVERRIDE { log_assert(module == mod); auto_reload_module = true; } - virtual void notify_connect(RTLIL::Module *mod, const std::vector&) - { - log_assert(module == mod); - auto_reload_module = true; - } - - virtual void notify_blackout(RTLIL::Module *mod) + virtual void notify_blackout(RTLIL::Module *mod) YS_OVERRIDE { log_assert(module == mod); auto_reload_module = true; From 3da46d3437f076c27cef5121f26a1fa151dde1f6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 28 Dec 2014 17:51:16 +0100 Subject: [PATCH 195/492] Renamed hashmap.h to hashlib.h, some related improvements --- kernel/{hashmap.h => hashlib.h} | 77 ++++++++++++++++----------------- kernel/modtools.h | 2 +- kernel/rtlil.cc | 18 +++++++- kernel/rtlil.h | 31 ++++++++++--- kernel/yosys.h | 36 ++++++++++++++- passes/cmds/delete.cc | 4 +- passes/cmds/splitnets.cc | 2 +- passes/opt/opt_clean.cc | 2 +- passes/opt/opt_const.cc | 2 +- passes/opt/opt_share.cc | 2 +- passes/opt/share.cc | 4 +- 11 files changed, 123 insertions(+), 57 deletions(-) rename kernel/{hashmap.h => hashlib.h} (90%) diff --git a/kernel/hashmap.h b/kernel/hashlib.h similarity index 90% rename from kernel/hashmap.h rename to kernel/hashlib.h index 431e8122e..a8d320865 100644 --- a/kernel/hashmap.h +++ b/kernel/hashlib.h @@ -1,29 +1,23 @@ -/* - * 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. - * - */ +// This is free and unencumbered software released into the public domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. -#ifndef YOSYS_HASHMAP_H +// ------------------------------------------------------- +// Written by Clifford Wolf in 2014 +// ------------------------------------------------------- + +#ifndef HASHLIB_H #include #include #include -#define YOSYS_HASHTABLE_SIZE_FACTOR 3 +namespace hashlib { + +#define HASHLIB_SIZE_FACTOR 3 // The XOR version of DJB2 // (traditionally 5381 is used as starting value for the djb2 hash) @@ -32,7 +26,7 @@ inline unsigned int mkhash(unsigned int a, unsigned int b) { } // The ADD version of DJB2 -// (use this version as last call for cache locality in b) +// (use this version for cache locality in b) inline unsigned int mkhash_add(unsigned int a, unsigned int b) { return ((a << 5) + a) + b; } @@ -47,10 +41,11 @@ template struct hash_ops { }; template<> struct hash_ops { - bool cmp(int a, int b) const { + template + bool cmp(T a, T b) const { return a == b; } - unsigned int hash(int a) const { + unsigned int hash(unsigned int a) const { return a; } }; @@ -97,7 +92,7 @@ struct hash_obj_ops { } template unsigned int hash(const T *a) const { - return a->name.hash(); + return a->hash(); } }; @@ -165,9 +160,9 @@ class dict entries.clear(); counter = other.size(); - int new_size = hashtable_size(YOSYS_HASHTABLE_SIZE_FACTOR * counter); + int new_size = hashtable_size(HASHLIB_SIZE_FACTOR * counter); hashtable.resize(new_size); - new_size = new_size / YOSYS_HASHTABLE_SIZE_FACTOR + 1; + new_size = new_size / HASHLIB_SIZE_FACTOR + 1; entries.reserve(new_size); for (auto &it : other) @@ -243,9 +238,9 @@ class dict if (free_list < 0) { int i = entries.size(); - int new_size = hashtable_size(YOSYS_HASHTABLE_SIZE_FACTOR * entries.size()); + int new_size = hashtable_size(HASHLIB_SIZE_FACTOR * entries.size()); hashtable.resize(new_size); - entries.resize(new_size / YOSYS_HASHTABLE_SIZE_FACTOR + 1); + entries.resize(new_size / HASHLIB_SIZE_FACTOR + 1); entries[i].udata = value; entries[i].set_next_used(0); counter++; @@ -345,14 +340,14 @@ public: insert(*first); } - iterator insert(const std::pair &value) + std::pair insert(const std::pair &value) { int hash = mkhash(value.first); int i = lookup_index(value.first, hash); if (i >= 0) - return iterator(this, i); + return std::pair(iterator(this, i), false); i = insert_at(value, hash); - return iterator(this, i); + return std::pair(iterator(this, i), true); } void erase(const K &key) @@ -497,9 +492,9 @@ class pool entries.clear(); counter = other.size(); - int new_size = hashtable_size(YOSYS_HASHTABLE_SIZE_FACTOR * counter); + int new_size = hashtable_size(HASHLIB_SIZE_FACTOR * counter); hashtable.resize(new_size); - new_size = new_size / YOSYS_HASHTABLE_SIZE_FACTOR + 1; + new_size = new_size / HASHLIB_SIZE_FACTOR + 1; entries.reserve(new_size); for (auto &it : other) @@ -575,9 +570,9 @@ class pool if (free_list < 0) { int i = entries.size(); - int new_size = hashtable_size(YOSYS_HASHTABLE_SIZE_FACTOR * entries.size()); + int new_size = hashtable_size(HASHLIB_SIZE_FACTOR * entries.size()); hashtable.resize(new_size); - entries.resize(new_size / YOSYS_HASHTABLE_SIZE_FACTOR + 1); + entries.resize(new_size / HASHLIB_SIZE_FACTOR + 1); entries[i].key = key; entries[i].set_next_used(0); counter++; @@ -677,14 +672,14 @@ public: insert(*first); } - iterator insert(const K &key) + std::pair insert(const K &key) { int hash = mkhash(key); int i = lookup_index(key, hash); if (i >= 0) - return iterator(this, i); + return std::pair(iterator(this, i), false); i = insert_at(key, hash); - return iterator(this, i); + return std::pair(iterator(this, i), true); } void erase(const K &key) @@ -695,8 +690,8 @@ public: void erase(const iterator it) { - int hash = mkhash(it->first); - do_erase(it->first, hash); + int hash = mkhash(*it); + do_erase(*it, hash); } int count(const K &key) const @@ -774,4 +769,6 @@ public: const_iterator end() const { return const_iterator(this, entries.size()); } }; +} /* namespace hashlib */ + #endif diff --git a/kernel/modtools.h b/kernel/modtools.h index 56362dbc8..558cc08b8 100644 --- a/kernel/modtools.h +++ b/kernel/modtools.h @@ -270,7 +270,7 @@ struct ModWalker dict> signal_consumers; pool signal_inputs, signal_outputs; - dict, hash_obj_ops> cell_outputs, cell_inputs; + dict> cell_outputs, cell_inputs; void add_wire(RTLIL::Wire *wire) { diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 23edcceef..c262801dc 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -236,6 +236,9 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) RTLIL::Design::Design() { + unsigned int hashidx_count = 0; + hashidx_ = hashidx_count++; + refcount_modules_ = 0; selection_stack.push_back(RTLIL::Selection()); } @@ -447,6 +450,9 @@ std::vector RTLIL::Design::selected_whole_modules_warn() const RTLIL::Module::Module() { + unsigned int hashidx_count = 0; + hashidx_ = hashidx_count++; + design = nullptr; refcount_wires_ = 0; refcount_cells_ = 0; @@ -1132,7 +1138,7 @@ namespace { struct DeleteWireWorker { RTLIL::Module *module; - const pool *wires_p; + const pool *wires_p; void operator()(RTLIL::SigSpec &sig) { std::vector chunks = sig; @@ -1146,7 +1152,7 @@ namespace { }; } -void RTLIL::Module::remove(const pool &wires) +void RTLIL::Module::remove(const pool &wires) { log_assert(refcount_wires_ == 0); @@ -1735,6 +1741,9 @@ RTLIL::Cell* RTLIL::Module::addDlatchsrGate(RTLIL::IdString name, RTLIL::SigSpec RTLIL::Wire::Wire() { + unsigned int hashidx_count = 0; + hashidx_ = hashidx_count++; + module = nullptr; width = 1; start_offset = 0; @@ -1746,12 +1755,17 @@ RTLIL::Wire::Wire() RTLIL::Memory::Memory() { + unsigned int hashidx_count = 0; + hashidx_ = hashidx_count++; + width = 1; size = 0; } RTLIL::Cell::Cell() : module(nullptr) { + unsigned int hashidx_count = 0; + hashidx_ = hashidx_count++; } bool RTLIL::Cell::hasPort(RTLIL::IdString portname) const diff --git a/kernel/rtlil.h b/kernel/rtlil.h index cb654c3af..8cf707999 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -708,8 +708,14 @@ struct RTLIL::Selection struct RTLIL::Monitor { - RTLIL::IdString name; - Monitor() { name = stringf("$%d", autoidx++); } + unsigned int hashidx_; + unsigned int hash() const { return hashidx_; } + + Monitor() { + unsigned int hashidx_count = 0; + hashidx_ = hashidx_count++; + } + virtual ~Monitor() { } virtual void notify_module_add(RTLIL::Module*) { } virtual void notify_module_del(RTLIL::Module*) { } @@ -721,7 +727,10 @@ struct RTLIL::Monitor struct RTLIL::Design { - pool monitors; + unsigned int hashidx_; + unsigned int hash() const { return hashidx_; } + + pool monitors; dict scratchpad; int refcount_modules_; @@ -802,13 +811,16 @@ struct RTLIL::Design struct RTLIL::Module { + unsigned int hashidx_; + unsigned int hash() const { return hashidx_; } + protected: void add(RTLIL::Wire *wire); void add(RTLIL::Cell *cell); public: RTLIL::Design *design; - pool monitors; + pool monitors; int refcount_wires_; int refcount_cells_; @@ -862,7 +874,7 @@ public: RTLIL::ObjRange cells() { return RTLIL::ObjRange(&cells_, &refcount_cells_); } // Removing wires is expensive. If you have to remove wires, remove them all at once. - void remove(const pool &wires); + void remove(const pool &wires); void remove(RTLIL::Cell *cell); void rename(RTLIL::Wire *wire, RTLIL::IdString new_name); @@ -1031,6 +1043,9 @@ public: struct RTLIL::Wire { + unsigned int hashidx_; + unsigned int hash() const { return hashidx_; } + protected: // use module->addWire() and module->remove() to create or destroy wires friend struct RTLIL::Module; @@ -1051,6 +1066,9 @@ public: struct RTLIL::Memory { + unsigned int hashidx_; + unsigned int hash() const { return hashidx_; } + Memory(); RTLIL::IdString name; @@ -1060,6 +1078,9 @@ struct RTLIL::Memory struct RTLIL::Cell { + unsigned int hashidx_; + unsigned int hash() const { return hashidx_; } + protected: // use module->addCell() and module->remove() to create or destroy cells friend struct RTLIL::Module; diff --git a/kernel/yosys.h b/kernel/yosys.h index d47f3a958..b653941ce 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -124,17 +124,51 @@ YOSYS_NAMESPACE_BEGIN -#include "kernel/hashmap.h" +#include "kernel/hashlib.h" using std::vector; +using std::string; +using hashlib::mkhash; +using hashlib::mkhash_add; +using hashlib::hash_ops; +using hashlib::hash_cstr_ops; +using hashlib::hash_ptr_ops; +using hashlib::hash_obj_ops; +using hashlib::dict; +using hashlib::pool; namespace RTLIL { struct IdString; + struct Const; struct SigBit; struct SigSpec; struct Wire; struct Cell; + struct Module; + struct Design; + struct Monitor; } +using RTLIL::IdString; +using RTLIL::Const; +using RTLIL::SigBit; +using RTLIL::SigSpec; +using RTLIL::Wire; +using RTLIL::Cell; +using RTLIL::Module; +using RTLIL::Design; + +template<> struct hash_ops : hash_obj_ops {}; +template<> struct hash_ops : hash_obj_ops {}; +template<> struct hash_ops : hash_obj_ops {}; +template<> struct hash_ops : hash_obj_ops {}; +template<> struct hash_ops : hash_obj_ops {}; + +template<> struct hash_ops : hash_obj_ops {}; +template<> struct hash_ops : hash_obj_ops {}; +template<> struct hash_ops : hash_obj_ops {}; +template<> struct hash_ops : hash_obj_ops {}; +template<> struct hash_ops : hash_obj_ops {}; + std::string stringf(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 1, 2)); std::string vstringf(const char *fmt, va_list ap); int readsome(std::istream &f, char *s, int n); diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc index 5bf2a36b8..b4362887e 100644 --- a/passes/cmds/delete.cc +++ b/passes/cmds/delete.cc @@ -91,8 +91,8 @@ struct DeletePass : public Pass { continue; } - pool delete_wires; - pool delete_cells; + pool delete_wires; + pool delete_cells; pool delete_procs; pool delete_mems; diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc index 2523c1660..d4e721a5d 100644 --- a/passes/cmds/splitnets.cc +++ b/passes/cmds/splitnets.cc @@ -176,7 +176,7 @@ struct SplitnetsPass : public Pass { module->rewrite_sigspecs(worker); - pool delete_wires; + pool delete_wires; for (auto &it : worker.splitmap) delete_wires.insert(it.first); module->remove(delete_wires); diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index b387e0381..b9ff5d302 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -262,7 +262,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } - pool del_wires; + pool del_wires; int del_wires_count = 0; for (auto wire : maybe_del_wires) diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc index f78ea6cc3..7f800bde9 100644 --- a/passes/opt/opt_const.cc +++ b/passes/opt/opt_const.cc @@ -199,7 +199,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons dict invert_map; TopoSort> cells; - dict, hash_obj_ops> cell_to_inbit; + dict> cell_to_inbit; dict> outbit_to_cell; for (auto cell : module->cells()) diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index 91bfd58ab..c581b749e 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -41,7 +41,7 @@ struct OptShareWorker CellTypes ct; int total_count; #ifdef USE_CELL_HASH_CACHE - dict cell_hash_cache; + dict cell_hash_cache; #endif #ifdef USE_CELL_HASH_CACHE diff --git a/passes/opt/share.cc b/passes/opt/share.cc index 41a4a6908..0d1a54d97 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -731,7 +731,7 @@ struct ShareWorker return forbidden_controls_cache.at(cell); pool pbits; - pool consumer_cells; + pool consumer_cells; modwalker.get_consumers(pbits, modwalker.cell_outputs[cell]); @@ -803,7 +803,7 @@ struct ShareWorker return activation_patterns_cache.at(cell); const pool &cell_out_bits = modwalker.cell_outputs[cell]; - pool driven_cells, driven_data_muxes; + pool driven_cells, driven_data_muxes; for (auto &bit : cell_out_bits) { From 89723a45cf86a508d052dd54aa058719e314cc3c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 28 Dec 2014 18:48:48 +0100 Subject: [PATCH 196/492] Improved hashlib iterator implementation --- kernel/hashlib.h | 60 +++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index a8d320865..d363d68b5 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -145,13 +145,14 @@ class dict std::vector hashtable; std::vector entries; - int free_list, counter; + int free_list, counter, begin_n; OPS ops; void init() { free_list = -1; counter = 0; + begin_n = -1; } void init_from(const dict &other) @@ -182,6 +183,7 @@ class dict void rehash() { free_list = -1; + begin_n = -1; for (auto &h : hashtable) h = -1; @@ -194,6 +196,7 @@ class dict int hash = mkhash(entries[i].udata.first); entries[i].set_next_used(hashtable[hash]); hashtable[hash] = i; + begin_n = i; } } @@ -213,7 +216,9 @@ class dict entries[index].set_next_free(free_list); free_list = index; if (--counter == 0) - init(); + clear(); + else if (index == begin_n) + do begin_n--; while (begin_n >= 0 && entries[begin_n].is_free()); return; } last_index = index; @@ -253,6 +258,8 @@ class dict entries[i].udata = value; entries[i].set_next_used(hashtable[hash]); hashtable[hash] = i; + if (begin_n < i) + begin_n = i; counter++; return i; } @@ -265,8 +272,7 @@ public: public: iterator() { } iterator(dict *ptr, int index) : ptr(ptr), index(index) { } - iterator operator++() { do index++; while (index != int(ptr->entries.size()) && ptr->entries[index].is_free()); return *this; } - iterator operator--() { do index--; while (index != 0 && ptr->entries[index].is_free()); return *this; } + iterator operator++() { do index--; while (index >= 0 && ptr->entries[index].is_free()); return *this; } bool operator==(const iterator &other) const { return index == other.index; } bool operator!=(const iterator &other) const { return index != other.index; } std::pair &operator*() { return ptr->entries[index].udata; } @@ -282,8 +288,7 @@ public: public: const_iterator() { } const_iterator(const dict *ptr, int index) : ptr(ptr), index(index) { } - const_iterator operator++() { do index++; while (index != int(ptr->entries.size()) && ptr->entries[index].is_free()); return *this; } - const_iterator operator--() { do index--; while (index != 0 && ptr->entries[index].is_free()); return *this; } + const_iterator operator++() { do index--; while (index >= 0 && ptr->entries[index].is_free()); return *this; } bool operator==(const const_iterator &other) const { return index == other.index; } bool operator!=(const const_iterator &other) const { return index != other.index; } const std::pair &operator*() const { return ptr->entries[index].udata; } @@ -308,8 +313,8 @@ public: } dict &operator=(const dict &other) { - clear(); - init_from(other); + if (this != &other) + init_from(other); return *this; } @@ -420,6 +425,7 @@ public: entries.swap(other.entries); std::swap(free_list, other.free_list); std::swap(counter, other.counter); + std::swap(begin_n, other.begin_n); } bool operator==(const dict &other) const { @@ -450,11 +456,11 @@ public: bool empty() const { return counter == 0; } void clear() { hashtable.clear(); entries.clear(); init(); } - iterator begin() { int index = 0; while (index != int(entries.size()) && entries[index].is_free()) index++; return iterator(this, index); } - iterator end() { return iterator(this, entries.size()); } + iterator begin() { return iterator(this, begin_n); } + iterator end() { return iterator(this, -1); } - const_iterator begin() const { int index = 0; while (index != int(entries.size()) && entries[index].is_free()) index++; return const_iterator(this, index); } - const_iterator end() const { return const_iterator(this, entries.size()); } + const_iterator begin() const { return const_iterator(this, begin_n); } + const_iterator end() const { return const_iterator(this, -1); } }; template> @@ -477,13 +483,14 @@ class pool std::vector hashtable; std::vector entries; - int free_list, counter; + int free_list, counter, begin_n; OPS ops; void init() { free_list = -1; counter = 0; + begin_n = -1; } void init_from(const pool &other) @@ -514,6 +521,7 @@ class pool void rehash() { free_list = -1; + begin_n = -1; for (auto &h : hashtable) h = -1; @@ -526,6 +534,7 @@ class pool int hash = mkhash(entries[i].key); entries[i].set_next_used(hashtable[hash]); hashtable[hash] = i; + begin_n = i; } } @@ -545,7 +554,9 @@ class pool entries[index].set_next_free(free_list); free_list = index; if (--counter == 0) - init(); + clear(); + else if (index == begin_n) + do begin_n--; while (begin_n >= 0 && entries[begin_n].is_free()); return; } last_index = index; @@ -585,6 +596,8 @@ class pool entries[i].key = key; entries[i].set_next_used(hashtable[hash]); hashtable[hash] = i; + if (begin_n < i) + begin_n = i; counter++; return i; } @@ -597,8 +610,7 @@ public: public: iterator() { } iterator(pool *ptr, int index) : ptr(ptr), index(index) { } - iterator operator++() { do index++; while (index != int(ptr->entries.size()) && ptr->entries[index].is_free()); return *this; } - iterator operator--() { do index--; while (index != 0 && ptr->entries[index].is_free()); return *this; } + iterator operator++() { do index--; while (index >= 0 && ptr->entries[index].is_free()); return *this; } bool operator==(const iterator &other) const { return index == other.index; } bool operator!=(const iterator &other) const { return index != other.index; } K &operator*() { return ptr->entries[index].key; } @@ -614,8 +626,7 @@ public: public: const_iterator() { } const_iterator(const pool *ptr, int index) : ptr(ptr), index(index) { } - const_iterator operator++() { do index++; while (index != int(ptr->entries.size()) && ptr->entries[index].is_free()); return *this; } - const_iterator operator--() { do index--; while (index != 0 && ptr->entries[index].is_free()); return *this; } + const_iterator operator++() { do index--; while (index >= 0 && ptr->entries[index].is_free()); return *this; } bool operator==(const const_iterator &other) const { return index == other.index; } bool operator!=(const const_iterator &other) const { return index != other.index; } const K &operator*() const { return ptr->entries[index].key; } @@ -640,8 +651,8 @@ public: } pool &operator=(const pool &other) { - clear(); - init_from(other); + if (this != &other) + init_from(other); return *this; } @@ -732,6 +743,7 @@ public: entries.swap(other.entries); std::swap(free_list, other.free_list); std::swap(counter, other.counter); + std::swap(begin_n, other.begin_n); } bool operator==(const pool &other) const { @@ -762,11 +774,11 @@ public: bool empty() const { return counter == 0; } void clear() { hashtable.clear(); entries.clear(); init(); } - iterator begin() { int index = 0; while (index != int(entries.size()) && entries[index].is_free()) index++; return iterator(this, index); } - iterator end() { return iterator(this, entries.size()); } + iterator begin() { return iterator(this, begin_n); } + iterator end() { return iterator(this, -1); } - const_iterator begin() const { int index = 0; while (index != int(entries.size()) && entries[index].is_free()) index++; return const_iterator(this, index); } - const_iterator end() const { return const_iterator(this, entries.size()); } + const_iterator begin() const { return const_iterator(this, begin_n); } + const_iterator end() const { return const_iterator(this, -1); } }; } /* namespace hashlib */ From f3a97b75c78bd6f3670445129405213c0a015481 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 28 Dec 2014 19:03:18 +0100 Subject: [PATCH 197/492] Fixed performance bug in object hashing --- kernel/rtlil.cc | 10 +++++----- kernel/rtlil.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index c262801dc..6f2d367d6 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -236,7 +236,7 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) RTLIL::Design::Design() { - unsigned int hashidx_count = 0; + static unsigned int hashidx_count = 0; hashidx_ = hashidx_count++; refcount_modules_ = 0; @@ -450,7 +450,7 @@ std::vector RTLIL::Design::selected_whole_modules_warn() const RTLIL::Module::Module() { - unsigned int hashidx_count = 0; + static unsigned int hashidx_count = 0; hashidx_ = hashidx_count++; design = nullptr; @@ -1741,7 +1741,7 @@ RTLIL::Cell* RTLIL::Module::addDlatchsrGate(RTLIL::IdString name, RTLIL::SigSpec RTLIL::Wire::Wire() { - unsigned int hashidx_count = 0; + static unsigned int hashidx_count = 0; hashidx_ = hashidx_count++; module = nullptr; @@ -1755,7 +1755,7 @@ RTLIL::Wire::Wire() RTLIL::Memory::Memory() { - unsigned int hashidx_count = 0; + static unsigned int hashidx_count = 0; hashidx_ = hashidx_count++; width = 1; @@ -1764,7 +1764,7 @@ RTLIL::Memory::Memory() RTLIL::Cell::Cell() : module(nullptr) { - unsigned int hashidx_count = 0; + static unsigned int hashidx_count = 0; hashidx_ = hashidx_count++; } diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 8cf707999..f759a014f 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -712,7 +712,7 @@ struct RTLIL::Monitor unsigned int hash() const { return hashidx_; } Monitor() { - unsigned int hashidx_count = 0; + static unsigned int hashidx_count = 0; hashidx_ = hashidx_count++; } From 137f35373f4ef0d1ddf212187e537e48d077b1f4 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 28 Dec 2014 19:24:24 +0100 Subject: [PATCH 198/492] Changed more code to dict<> and pool<> --- frontends/ast/ast.cc | 2 +- frontends/ast/ast.h | 4 ++-- frontends/ast/genrtlil.cc | 6 +++--- kernel/celltypes.h | 12 ++++++------ kernel/utils.h | 10 +++++----- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 0f79352f7..8ef60079b 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -56,7 +56,7 @@ namespace AST_INTERNAL { bool flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire; AstNode *current_ast, *current_ast_mod; std::map current_scope; - const std::map *genRTLIL_subst_ptr = NULL; + const dict *genRTLIL_subst_ptr = NULL; RTLIL::SigSpec ignoreThisSignalsInInitial; AstNode *current_top_block, *current_block, *current_block_child; AstModule *current_module; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 27cf0ef3d..1a7ac576b 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -231,7 +231,7 @@ namespace AST // for expressions the resulting signal vector is returned // all generated cell instances, etc. are written to the RTLIL::Module pointed to by AST_INTERNAL::current_module RTLIL::SigSpec genRTLIL(int width_hint = -1, bool sign_hint = false); - RTLIL::SigSpec genWidthRTLIL(int width, const std::map *new_subst_ptr = NULL); + RTLIL::SigSpec genWidthRTLIL(int width, const dict *new_subst_ptr = NULL); // compare AST nodes bool operator==(const AstNode &other) const; @@ -293,7 +293,7 @@ namespace AST_INTERNAL extern bool flag_dump_ast1, flag_dump_ast2, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire; extern AST::AstNode *current_ast, *current_ast_mod; extern std::map current_scope; - extern const std::map *genRTLIL_subst_ptr; + extern const dict *genRTLIL_subst_ptr; extern RTLIL::SigSpec ignoreThisSignalsInInitial; extern AST::AstNode *current_top_block, *current_block, *current_block_child; extern AST::AstModule *current_module; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 238da2634..a86d08d56 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -254,7 +254,7 @@ struct AST_INTERNAL::ProcessGenerator // create initial assignments for the temporary signals if ((flag_nolatches || always->get_bool_attribute("\\nolatches") || current_module->get_bool_attribute("\\nolatches")) && !found_clocked_sync) { - subst_rvalue_map = subst_lvalue_from.to_sigbit_map(RTLIL::SigSpec(RTLIL::State::Sx, GetSize(subst_lvalue_from))); + subst_rvalue_map = subst_lvalue_from.to_sigbit_dict(RTLIL::SigSpec(RTLIL::State::Sx, GetSize(subst_lvalue_from))); } else { addChunkActions(current_case->actions, subst_lvalue_to, subst_lvalue_from); } @@ -1391,9 +1391,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // this is a wrapper for AstNode::genRTLIL() when a specific signal width is requested and/or // signals must be substituted before beeing used as input values (used by ProcessGenerator) // note that this is using some global variables to communicate this special settings to AstNode::genRTLIL(). -RTLIL::SigSpec AstNode::genWidthRTLIL(int width, const std::map *new_subst_ptr) +RTLIL::SigSpec AstNode::genWidthRTLIL(int width, const dict *new_subst_ptr) { - const std::map *backup_subst_ptr = genRTLIL_subst_ptr; + const dict *backup_subst_ptr = genRTLIL_subst_ptr; if (new_subst_ptr) genRTLIL_subst_ptr = new_subst_ptr; diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 5ba4dd88b..32e144194 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -27,13 +27,13 @@ YOSYS_NAMESPACE_BEGIN struct CellType { RTLIL::IdString type; - std::set inputs, outputs; + pool inputs, outputs; bool is_evaluable; }; struct CellTypes { - std::map cell_types; + dict cell_types; CellTypes() { @@ -55,7 +55,7 @@ struct CellTypes setup_stdcells_mem(); } - void setup_type(RTLIL::IdString type, const std::set &inputs, const std::set &outputs, bool is_evaluable = false) + void setup_type(RTLIL::IdString type, const pool &inputs, const pool &outputs, bool is_evaluable = false) { CellType ct = {type, inputs, outputs, is_evaluable}; cell_types[ct.type] = ct; @@ -63,7 +63,7 @@ struct CellTypes void setup_module(RTLIL::Module *module) { - std::set inputs, outputs; + pool inputs, outputs; for (RTLIL::IdString wire_name : module->ports) { RTLIL::Wire *wire = module->wire(wire_name); if (wire->port_input) @@ -109,7 +109,7 @@ struct CellTypes setup_type("$alu", {"\\A", "\\B", "\\CI", "\\BI"}, {"\\X", "\\Y", "\\CO"}, true); setup_type("$fa", {"\\A", "\\B", "\\C"}, {"\\X", "\\Y"}, true); - setup_type("$assert", {"\\A", "\\EN"}, std::set(), true); + setup_type("$assert", {"\\A", "\\EN"}, pool(), true); } void setup_internals_mem() @@ -123,7 +123,7 @@ struct CellTypes setup_type("$dlatchsr", {"\\EN", "\\SET", "\\CLR", "\\D"}, {"\\Q"}); setup_type("$memrd", {"\\CLK", "\\ADDR"}, {"\\DATA"}); - setup_type("$memwr", {"\\CLK", "\\EN", "\\ADDR", "\\DATA"}, std::set()); + setup_type("$memwr", {"\\CLK", "\\EN", "\\ADDR", "\\DATA"}, pool()); setup_type("$mem", {"\\RD_CLK", "\\RD_ADDR", "\\WR_CLK", "\\WR_EN", "\\WR_ADDR", "\\WR_DATA"}, {"\\RD_DATA"}); setup_type("$fsm", {"\\CLK", "\\ARST", "\\CTRL_IN"}, {"\\CTRL_OUT"}); diff --git a/kernel/utils.h b/kernel/utils.h index 479effdc9..2ec6182ea 100644 --- a/kernel/utils.h +++ b/kernel/utils.h @@ -31,17 +31,17 @@ YOSYS_NAMESPACE_BEGIN // A map-like container, but you can save and restore the state // ------------------------------------------------ -template> +template> struct stackmap { private: - std::vector> backup_state; - std::map current_state; + std::vector> backup_state; + dict current_state; static T empty_tuple; public: stackmap() { } - stackmap(const std::map &other) : current_state(other) { } + stackmap(const dict &other) : current_state(other) { } template void operator=(const Other &other) @@ -94,7 +94,7 @@ public: current_state.erase(k); } - const std::map &stdmap() + const dict &stdmap() { return current_state; } From 951c72ba52be44f9a3133c6ab3af56bdb92087ac Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 28 Dec 2014 21:26:36 +0100 Subject: [PATCH 199/492] bugfix in opt_share --- passes/opt/opt_share.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index c581b749e..66e29b66a 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -270,6 +270,7 @@ struct OptShareWorker } } log(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str()); + cell_hash_cache.erase(cell); module->remove(cell); total_count++; } else { From 445686cba38e949e85031ff95858c21afd1e1463 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 28 Dec 2014 21:27:05 +0100 Subject: [PATCH 200/492] using dict and pool in opt_reduce --- passes/opt/opt_reduce.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/passes/opt/opt_reduce.cc b/passes/opt/opt_reduce.cc index 3183d973d..3e324ccef 100644 --- a/passes/opt/opt_reduce.cc +++ b/passes/opt/opt_reduce.cc @@ -37,14 +37,14 @@ struct OptReduceWorker int total_count; bool did_something; - void opt_reduce(std::set &cells, SigSet &drivers, RTLIL::Cell *cell) + void opt_reduce(pool &cells, SigSet &drivers, RTLIL::Cell *cell) { if (cells.count(cell) == 0) return; cells.erase(cell); RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); - std::set new_sig_a_bits; + pool new_sig_a_bits; for (auto &bit : sig_a.to_sigbit_set()) { @@ -74,7 +74,7 @@ struct OptReduceWorker if (child_cell->type == cell->type) { opt_reduce(cells, drivers, child_cell); if (child_cell->getPort("\\Y")[0] == bit) { - std::set child_sig_a_bits = assign_map(child_cell->getPort("\\A")).to_sigbit_set(); + pool child_sig_a_bits = assign_map(child_cell->getPort("\\A")).to_sigbit_pool(); new_sig_a_bits.insert(child_sig_a_bits.begin(), child_sig_a_bits.end()); } else new_sig_a_bits.insert(RTLIL::State::S0); @@ -105,7 +105,7 @@ struct OptReduceWorker RTLIL::SigSpec sig_s = assign_map(cell->getPort("\\S")); RTLIL::SigSpec new_sig_b, new_sig_s; - std::set handled_sig; + pool handled_sig; handled_sig.insert(sig_a); for (int i = 0; i < sig_s.size(); i++) @@ -290,7 +290,7 @@ struct OptReduceWorker for (auto type : type_list) { SigSet drivers; - std::set cells; + pool cells; for (auto &cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; From 8773fd5897d1057dc8f87d4ffd13c96a708080e8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 28 Dec 2014 21:27:51 +0100 Subject: [PATCH 201/492] Added memhasher (yosys -M) --- kernel/driver.cc | 11 +++++++++-- kernel/rtlil.cc | 3 +++ kernel/yosys.cc | 37 +++++++++++++++++++++++++++++++++++++ kernel/yosys.h | 7 +++++++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index 4700bf61b..9a81d8a48 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -151,8 +151,11 @@ int main(int argc, char **argv) printf(" -m module_file\n"); printf(" load the specified module (aka plugin)\n"); printf("\n"); + printf(" -M\n"); + printf(" will slightly randomize allocated pointer addresses. for debugging\n"); + printf("\n"); printf(" -A\n"); - printf(" will call abort() at the end of the script. useful for debugging\n"); + printf(" will call abort() at the end of the script. for debugging\n"); printf("\n"); printf(" -V\n"); printf(" print version information and exit\n"); @@ -174,10 +177,13 @@ int main(int argc, char **argv) } int opt; - while ((opt = getopt(argc, argv, "AQTVSm:f:Hh:b:o:p:l:qv:tds:c:")) != -1) + while ((opt = getopt(argc, argv, "MAQTVSm:f:Hh:b:o:p:l:qv:tds:c:")) != -1) { switch (opt) { + case 'M': + memhasher_on(); + break; case 'A': call_abort = true; break; @@ -407,6 +413,7 @@ int main(int argc, char **argv) } #endif + memhasher_off(); if (call_abort) abort(); diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 6f2d367d6..cdbaa5bbf 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1766,6 +1766,9 @@ RTLIL::Cell::Cell() : module(nullptr) { static unsigned int hashidx_count = 0; hashidx_ = hashidx_count++; + + // log("#memtrace# %p\n", this); + memhasher(); } bool RTLIL::Cell::hasPort(RTLIL::IdString portname) const diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 6cc643152..52bd066b7 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -55,6 +55,43 @@ RTLIL::Design *yosys_design = NULL; Tcl_Interp *yosys_tcl_interp = NULL; #endif +bool memhasher_active = false; +uint32_t memhasher_rng; +std::vector memhasher_store; + +void memhasher_on() +{ + memhasher_rng += time(NULL) << 16 ^ getpid(); + memhasher_store.resize(0x10000); + memhasher_active = true; +} + +void memhasher_off() +{ + for (auto p : memhasher_store) + if (p) free(p); + memhasher_store.clear(); + memhasher_active = false; +} + +void memhasher_do() +{ + memhasher_rng ^= memhasher_rng << 13; + memhasher_rng ^= memhasher_rng >> 17; + memhasher_rng ^= memhasher_rng << 5; + + int size, index = (memhasher_rng >> 4) & 0xffff; + switch (memhasher_rng & 7) { + case 0: size = 16; break; + case 1: size = 256; break; + case 2: size = 1024; break; + case 3: size = 4096; break; + default: size = 0; + } + if (index < 16) size *= 16; + memhasher_store[index] = realloc(memhasher_store[index], size); +} + std::string stringf(const char *fmt, ...) { std::string string; diff --git a/kernel/yosys.h b/kernel/yosys.h index b653941ce..50a159939 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -169,6 +169,13 @@ template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; +void memhasher_on(); +void memhasher_off(); +void memhasher_do(); + +extern bool memhasher_active; +inline void memhasher() { if (memhasher_active) memhasher_do(); } + std::string stringf(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 1, 2)); std::string vstringf(const char *fmt, va_list ap); int readsome(std::istream &f, char *s, int n); From 2ad131764fc9b9b3f913650d206a540c2d57dc45 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 28 Dec 2014 21:43:14 +0100 Subject: [PATCH 202/492] Some cleanups --- kernel/hashlib.h | 18 +++++++++--------- kernel/yosys.cc | 4 +++- kernel/yosys.h | 9 ++++++++- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index d363d68b5..e5e76a1e1 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -17,7 +17,7 @@ namespace hashlib { -#define HASHLIB_SIZE_FACTOR 3 +const int config_size_factor = 3; // The XOR version of DJB2 // (traditionally 5381 is used as starting value for the djb2 hash) @@ -161,9 +161,9 @@ class dict entries.clear(); counter = other.size(); - int new_size = hashtable_size(HASHLIB_SIZE_FACTOR * counter); + int new_size = hashtable_size(config_size_factor * counter); hashtable.resize(new_size); - new_size = new_size / HASHLIB_SIZE_FACTOR + 1; + new_size = new_size / config_size_factor + 1; entries.reserve(new_size); for (auto &it : other) @@ -243,9 +243,9 @@ class dict if (free_list < 0) { int i = entries.size(); - int new_size = hashtable_size(HASHLIB_SIZE_FACTOR * entries.size()); + int new_size = hashtable_size(config_size_factor * entries.size()); hashtable.resize(new_size); - entries.resize(new_size / HASHLIB_SIZE_FACTOR + 1); + entries.resize(new_size / config_size_factor + 1); entries[i].udata = value; entries[i].set_next_used(0); counter++; @@ -499,9 +499,9 @@ class pool entries.clear(); counter = other.size(); - int new_size = hashtable_size(HASHLIB_SIZE_FACTOR * counter); + int new_size = hashtable_size(config_size_factor * counter); hashtable.resize(new_size); - new_size = new_size / HASHLIB_SIZE_FACTOR + 1; + new_size = new_size / config_size_factor + 1; entries.reserve(new_size); for (auto &it : other) @@ -581,9 +581,9 @@ class pool if (free_list < 0) { int i = entries.size(); - int new_size = hashtable_size(HASHLIB_SIZE_FACTOR * entries.size()); + int new_size = hashtable_size(config_size_factor * entries.size()); hashtable.resize(new_size); - entries.resize(new_size / HASHLIB_SIZE_FACTOR + 1); + entries.resize(new_size / config_size_factor + 1); entries[i].key = key; entries[i].set_next_used(0); counter++; diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 52bd066b7..0faca8d51 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -56,12 +56,14 @@ Tcl_Interp *yosys_tcl_interp = NULL; #endif bool memhasher_active = false; -uint32_t memhasher_rng; +uint32_t memhasher_rng = 123456; std::vector memhasher_store; void memhasher_on() { +#ifdef __linux__ memhasher_rng += time(NULL) << 16 ^ getpid(); +#endif memhasher_store.resize(0x10000); memhasher_active = true; } diff --git a/kernel/yosys.h b/kernel/yosys.h index 50a159939..bbcbd5fed 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -124,7 +124,14 @@ YOSYS_NAMESPACE_BEGIN -#include "kernel/hashlib.h" +#ifdef HASHLIB_H +# undef HASHLIB_H +# include "kernel/hashlib.h" +#else +# include "kernel/hashlib.h" +# undef HASHLIB_H +#endif + using std::vector; using std::string; using hashlib::mkhash; From dede5353b10c1d8fb887fbfd3a46cb1fc0413082 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 28 Dec 2014 22:26:09 +0100 Subject: [PATCH 203/492] Some changes to hashlib to make for better stl compatibility --- kernel/hashlib.h | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index e5e76a1e1..24a1dbf6d 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -200,13 +200,13 @@ class dict } } - void do_erase(const K &key, int hash) + int do_erase(const K &key, int hash) { int last_index = -1; int index = hashtable.empty() ? -1 : hashtable[hash]; while (1) { if (index < 0) - return; + return 0; if (ops.cmp(entries[index].udata.first, key)) { if (last_index < 0) hashtable[hash] = entries[index].get_next(); @@ -219,7 +219,7 @@ class dict clear(); else if (index == begin_n) do begin_n--; while (begin_n >= 0 && entries[begin_n].is_free()); - return; + return 1; } last_index = index; index = entries[index].get_next(); @@ -355,16 +355,17 @@ public: return std::pair(iterator(this, i), true); } - void erase(const K &key) + int erase(const K &key) { int hash = mkhash(key); - do_erase(key, hash); + return do_erase(key, hash); } - void erase(const iterator it) + iterator erase(iterator it) { int hash = mkhash(it->first); do_erase(it->first, hash); + return ++it; } int count(const K &key) const @@ -538,13 +539,13 @@ class pool } } - void do_erase(const K &key, int hash) + int do_erase(const K &key, int hash) { int last_index = -1; int index = hashtable.empty() ? -1 : hashtable[hash]; while (1) { if (index < 0) - return; + return 0; if (ops.cmp(entries[index].key, key)) { if (last_index < 0) hashtable[hash] = entries[index].get_next(); @@ -557,7 +558,7 @@ class pool clear(); else if (index == begin_n) do begin_n--; while (begin_n >= 0 && entries[begin_n].is_free()); - return; + return 1; } last_index = index; index = entries[index].get_next(); @@ -693,16 +694,17 @@ public: return std::pair(iterator(this, i), true); } - void erase(const K &key) + int erase(const K &key) { int hash = mkhash(key); - do_erase(key, hash); + return do_erase(key, hash); } - void erase(const iterator it) + iterator erase(iterator it) { int hash = mkhash(*it); do_erase(*it, hash); + return ++it; } int count(const K &key) const From a2226e530791ec9dea45cd905f812de28d2c1c06 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 00:12:36 +0100 Subject: [PATCH 204/492] Added mkhash_xorshift() --- kernel/hashlib.h | 20 +++++++++++++++++++- kernel/rtlil.cc | 25 +++++++++++++++---------- kernel/rtlil.h | 5 +++-- kernel/yosys.h | 1 + 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 24a1dbf6d..021cc66ee 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -31,6 +31,20 @@ inline unsigned int mkhash_add(unsigned int a, unsigned int b) { return ((a << 5) + a) + b; } +inline unsigned int mkhash_xorshift(unsigned int a) { + if (sizeof(a) == 4) { + a ^= a << 13; + a ^= a >> 17; + a ^= a << 5; + } else if (sizeof(a) == 8) { + a ^= a << 13; + a ^= a >> 7; + a ^= a << 17; + } else + throw std::runtime_error("mkhash_xorshift() only implemented for 32 bit and 64 bit ints"); + return a; +} + template struct hash_ops { bool cmp(const T &a, const T &b) const { return a == b; @@ -122,7 +136,11 @@ inline int hashtable_size(int old_size) if (old_size < 250999999) return 250999999; if (old_size < 503000009) return 503000009; if (old_size < 1129999999) return 1129999999; - throw std::length_error("hash table exceeded maximum size"); + + if (sizeof(old_size) == 4) + throw std::length_error("hash table exceeded maximum size. recompile with -mint64."); + + return old_size * 2; } template> diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index cdbaa5bbf..f25df175d 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -236,8 +236,9 @@ void RTLIL::Selection::optimize(RTLIL::Design *design) RTLIL::Design::Design() { - static unsigned int hashidx_count = 0; - hashidx_ = hashidx_count++; + static unsigned int hashidx_count = 123456789; + hashidx_count = mkhash_xorshift(hashidx_count); + hashidx_ = hashidx_count; refcount_modules_ = 0; selection_stack.push_back(RTLIL::Selection()); @@ -450,8 +451,9 @@ std::vector RTLIL::Design::selected_whole_modules_warn() const RTLIL::Module::Module() { - static unsigned int hashidx_count = 0; - hashidx_ = hashidx_count++; + static unsigned int hashidx_count = 123456789; + hashidx_count = mkhash_xorshift(hashidx_count); + hashidx_ = hashidx_count; design = nullptr; refcount_wires_ = 0; @@ -1741,8 +1743,9 @@ RTLIL::Cell* RTLIL::Module::addDlatchsrGate(RTLIL::IdString name, RTLIL::SigSpec RTLIL::Wire::Wire() { - static unsigned int hashidx_count = 0; - hashidx_ = hashidx_count++; + static unsigned int hashidx_count = 123456789; + hashidx_count = mkhash_xorshift(hashidx_count); + hashidx_ = hashidx_count; module = nullptr; width = 1; @@ -1755,8 +1758,9 @@ RTLIL::Wire::Wire() RTLIL::Memory::Memory() { - static unsigned int hashidx_count = 0; - hashidx_ = hashidx_count++; + static unsigned int hashidx_count = 123456789; + hashidx_count = mkhash_xorshift(hashidx_count); + hashidx_ = hashidx_count; width = 1; size = 0; @@ -1764,8 +1768,9 @@ RTLIL::Memory::Memory() RTLIL::Cell::Cell() : module(nullptr) { - static unsigned int hashidx_count = 0; - hashidx_ = hashidx_count++; + static unsigned int hashidx_count = 123456789; + hashidx_count = mkhash_xorshift(hashidx_count); + hashidx_ = hashidx_count; // log("#memtrace# %p\n", this); memhasher(); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index f759a014f..5bca060f4 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -712,8 +712,9 @@ struct RTLIL::Monitor unsigned int hash() const { return hashidx_; } Monitor() { - static unsigned int hashidx_count = 0; - hashidx_ = hashidx_count++; + static unsigned int hashidx_count = 123456789; + hashidx_count = mkhash_xorshift(hashidx_count); + hashidx_ = hashidx_count; } virtual ~Monitor() { } diff --git a/kernel/yosys.h b/kernel/yosys.h index bbcbd5fed..8ddd6f540 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -136,6 +136,7 @@ using std::vector; using std::string; using hashlib::mkhash; using hashlib::mkhash_add; +using hashlib::mkhash_xorshift; using hashlib::hash_ops; using hashlib::hash_cstr_ops; using hashlib::hash_ptr_ops; From 9ff3a9f30da0cade42db433f94a408f4d9349ba2 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 00:42:48 +0100 Subject: [PATCH 205/492] Switched most of "share" to dict<> and pool<> --- passes/opt/share.cc | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/passes/opt/share.cc b/passes/opt/share.cc index 0d1a54d97..2a81a63f5 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -41,7 +41,7 @@ struct ShareWorkerConfig struct ShareWorker { ShareWorkerConfig config; - std::set generic_ops; + pool generic_ops; RTLIL::Design *design; RTLIL::Module *module; @@ -69,7 +69,7 @@ struct ShareWorker void find_terminal_bits() { std::set queue_bits; - std::set visited_cells; + pool visited_cells; queue_bits.insert(modwalker.signal_outputs.begin(), modwalker.signal_outputs.end()); @@ -161,7 +161,7 @@ struct ShareWorker } int share_macc_ports(Macc::port_t &p1, Macc::port_t &p2, int w1, int w2, - RTLIL::SigSpec act = RTLIL::SigSpec(), Macc *supermacc = nullptr, std::set *supercell_aux = nullptr) + RTLIL::SigSpec act = RTLIL::SigSpec(), Macc *supermacc = nullptr, pool *supercell_aux = nullptr) { if (p1.do_subtract != p2.do_subtract) return -1; @@ -237,7 +237,7 @@ struct ShareWorker } int share_macc(RTLIL::Cell *c1, RTLIL::Cell *c2, - RTLIL::SigSpec act = RTLIL::SigSpec(), RTLIL::Cell *supercell = nullptr, std::set *supercell_aux = nullptr) + RTLIL::SigSpec act = RTLIL::SigSpec(), RTLIL::Cell *supercell = nullptr, pool *supercell_aux = nullptr) { Macc m1(c1), m2(c2), supermacc; @@ -345,7 +345,7 @@ struct ShareWorker // Find shareable cells and compatible groups of cells // --------------------------------------------------- - std::set> shareable_cells; + pool shareable_cells; void find_shareable_cells() { @@ -501,7 +501,7 @@ struct ShareWorker // Create replacement cell // ----------------------- - RTLIL::Cell *make_supercell(RTLIL::Cell *c1, RTLIL::Cell *c2, RTLIL::SigSpec act, std::set &supercell_aux) + RTLIL::Cell *make_supercell(RTLIL::Cell *c1, RTLIL::Cell *c2, RTLIL::SigSpec act, pool &supercell_aux) { log_assert(c1->type == c2->type); @@ -718,7 +718,7 @@ struct ShareWorker // Finding forbidden control inputs for a cell // ------------------------------------------- - std::map> forbidden_controls_cache; + dict> forbidden_controls_cache; const std::set &find_forbidden_controls(RTLIL::Cell *cell) { @@ -760,6 +760,7 @@ struct ShareWorker // Finding control inputs and activation pattern for a cell // -------------------------------------------------------- + // FIXME: For some reasone this must be std::map<> and not dict<> std::map>> activation_patterns_cache; bool sort_check_activation_pattern(std::pair &p) @@ -911,7 +912,7 @@ struct ShareWorker } } - RTLIL::SigSpec make_cell_activation_logic(const std::set> &activation_patterns, std::set &supercell_aux) + RTLIL::SigSpec make_cell_activation_logic(const std::set> &activation_patterns, pool &supercell_aux) { RTLIL::Wire *all_cases_wire = module->addWire(NEW_ID, 0); @@ -945,8 +946,8 @@ struct ShareWorker topo_sigmap.set(module); topo_bit_drivers.clear(); - std::map> cell_to_bits; - std::map> bit_to_cells; + dict> cell_to_bits; + dict> bit_to_cells; for (auto cell : module->cells()) if (ct.cell_known(cell->type)) @@ -983,7 +984,7 @@ struct ShareWorker return found_scc; } - bool find_in_input_cone_worker(RTLIL::Cell *root, RTLIL::Cell *needle, std::set &stop) + bool find_in_input_cone_worker(RTLIL::Cell *root, RTLIL::Cell *needle, pool &stop) { if (root == needle) return true; @@ -1001,7 +1002,7 @@ struct ShareWorker bool find_in_input_cone(RTLIL::Cell *root, RTLIL::Cell *needle) { - std::set stop; + pool stop; return find_in_input_cone_worker(root, needle, stop); } @@ -1011,12 +1012,12 @@ struct ShareWorker ct.setup_internals(); ct.setup_stdcells(); - std::set queue, covered; + pool queue, covered; queue.insert(cell); while (!queue.empty()) { - std::set new_queue; + pool new_queue; for (auto c : queue) { if (!ct.cell_known(c->type)) @@ -1170,7 +1171,7 @@ struct ShareWorker ezDefaultSAT ez; SatGen satgen(&ez, &modwalker.sigmap); - std::set sat_cells; + pool sat_cells; std::set bits_queue; std::vector cell_active, other_cell_active; @@ -1277,7 +1278,7 @@ struct ShareWorker other_cell_select_score += p.first.size(); RTLIL::Cell *supercell; - std::set supercell_aux; + pool supercell_aux; if (cell_select_score <= other_cell_select_score) { RTLIL::SigSpec act = make_cell_activation_logic(filtered_cell_activation_patterns, supercell_aux); supercell = make_supercell(cell, other_cell, act, supercell_aux); From cfe0817697c9e7a656fd3a64e3a9014fa86e78d0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 02:01:42 +0100 Subject: [PATCH 206/492] Converting "share" to dict<> and pool<> complete --- kernel/hashlib.h | 11 +++++++ kernel/rtlil.h | 11 +++++-- passes/opt/share.cc | 76 +++++++++++++++++++++++++-------------------- 3 files changed, 62 insertions(+), 36 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 021cc66ee..4e8c00026 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -76,6 +76,17 @@ template<> struct hash_ops { } }; +template struct hash_ops> { + bool cmp(std::pair a, std::pair b) const { + return a == b; + } + unsigned int hash(std::pair a) const { + hash_ops

p_ops; + hash_ops q_ops; + return mkhash(p_ops.hash(a.first), q_ops.hash(a.second)); + } +}; + struct hash_cstr_ops { bool cmp(const char *a, const char *b) const { for (int i = 0; a[i] || b[i]; i++) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 5bca060f4..25477d02e 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -219,8 +219,8 @@ namespace RTLIL return index_; } - // The following is a helper key_compare class. Instead of for example pool - // use pool> if the order of cells in the + // The following is a helper key_compare class. Instead of for example std::set + // use std::set> if the order of cells in the // set has an influence on the algorithm. template struct compare_ptr_by_name { @@ -450,6 +450,13 @@ struct RTLIL::Const std::string decode_string() const; inline int size() const { return bits.size(); } + + inline unsigned int hash() const { + unsigned int h = 5381; + for (auto b : bits) + mkhash(h, b); + return h; + } }; struct RTLIL::SigChunk diff --git a/passes/opt/share.cc b/passes/opt/share.cc index 2a81a63f5..e2c31bec5 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -28,6 +28,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN typedef RTLIL::IdString::compare_ptr_by_name cell_ptr_cmp; +typedef std::pair ssc_pair_t; struct ShareWorkerConfig { @@ -35,7 +36,7 @@ struct ShareWorkerConfig bool opt_force; bool opt_aggressive; bool opt_fast; - std::set generic_uni_ops, generic_bin_ops, generic_cbin_ops, generic_other_ops; + pool generic_uni_ops, generic_bin_ops, generic_cbin_ops, generic_other_ops; }; struct ShareWorker @@ -50,8 +51,8 @@ struct ShareWorker ModWalker modwalker; ModIndex mi; - std::set cells_to_remove; - std::set recursion_state; + pool cells_to_remove; + pool recursion_state; SigMap topo_sigmap; std::map, cell_ptr_cmp> topo_cell_drivers; @@ -64,11 +65,11 @@ struct ShareWorker // Find terminal bits -- i.e. bits that do not (exclusively) feed into a mux tree // ------------------------------------------------------------------------------ - std::set terminal_bits; + pool terminal_bits; void find_terminal_bits() { - std::set queue_bits; + pool queue_bits; pool visited_cells; queue_bits.insert(modwalker.signal_outputs.begin(), modwalker.signal_outputs.end()); @@ -718,12 +719,12 @@ struct ShareWorker // Finding forbidden control inputs for a cell // ------------------------------------------- - dict> forbidden_controls_cache; + std::map, cell_ptr_cmp> forbidden_controls_cache; - const std::set &find_forbidden_controls(RTLIL::Cell *cell) + const pool &find_forbidden_controls(RTLIL::Cell *cell) { if (recursion_state.count(cell)) { - static std::set empty_controls_set; + static pool empty_controls_set; return empty_controls_set; } @@ -745,7 +746,7 @@ struct ShareWorker for (auto c : consumer_cells) if (fwd_ct.cell_known(c->type)) { - const std::set &bits = find_forbidden_controls(c); + const pool &bits = find_forbidden_controls(c); forbidden_controls_cache[cell].insert(bits.begin(), bits.end()); } @@ -760,10 +761,9 @@ struct ShareWorker // Finding control inputs and activation pattern for a cell // -------------------------------------------------------- - // FIXME: For some reasone this must be std::map<> and not dict<> - std::map>> activation_patterns_cache; + std::map, cell_ptr_cmp> activation_patterns_cache; - bool sort_check_activation_pattern(std::pair &p) + bool sort_check_activation_pattern(ssc_pair_t &p) { std::map p_bits; @@ -787,16 +787,16 @@ struct ShareWorker return true; } - void optimize_activation_patterns(std::set> & /* patterns */) + void optimize_activation_patterns(pool & /* patterns */) { // TODO: Remove patterns that are contained in other patterns // TODO: Consolidate pairs of patterns that only differ in the value for one signal bit } - const std::set> &find_cell_activation_patterns(RTLIL::Cell *cell, const char *indent) + const pool &find_cell_activation_patterns(RTLIL::Cell *cell, const char *indent) { if (recursion_state.count(cell)) { - static std::set> empty_patterns_set; + static pool empty_patterns_set; return empty_patterns_set; } @@ -810,7 +810,7 @@ struct ShareWorker { if (terminal_bits.count(bit)) { // Terminal cells are always active: unconditional activation pattern - activation_patterns_cache[cell].insert(std::pair()); + activation_patterns_cache[cell].insert(ssc_pair_t()); return activation_patterns_cache.at(cell); } for (auto &pbit : modwalker.signal_consumers[bit]) { @@ -826,7 +826,7 @@ struct ShareWorker for (auto c : driven_data_muxes) { - const std::set> &c_patterns = find_cell_activation_patterns(c, indent); + const pool &c_patterns = find_cell_activation_patterns(c, indent); bool used_in_a = false; std::set used_in_b_parts; @@ -861,7 +861,7 @@ struct ShareWorker } for (auto c : driven_cells) { - const std::set> &c_patterns = find_cell_activation_patterns(c, indent); + const pool &c_patterns = find_cell_activation_patterns(c, indent); activation_patterns_cache[cell].insert(c_patterns.begin(), c_patterns.end()); } @@ -879,7 +879,7 @@ struct ShareWorker return activation_patterns_cache[cell]; } - RTLIL::SigSpec bits_from_activation_patterns(const std::set> &activation_patterns) + RTLIL::SigSpec bits_from_activation_patterns(const pool &activation_patterns) { std::set all_bits; for (auto &it : activation_patterns) { @@ -894,13 +894,13 @@ struct ShareWorker return signal; } - void filter_activation_patterns(std::set> &out, - const std::set> &in, const std::set &filter_bits) + void filter_activation_patterns(pool &out, + const pool &in, const std::set &filter_bits) { for (auto &p : in) { std::vector p_first = p.first; - std::pair new_p; + ssc_pair_t new_p; for (int i = 0; i < GetSize(p_first); i++) if (filter_bits.count(p_first[i]) == 0) { @@ -912,7 +912,7 @@ struct ShareWorker } } - RTLIL::SigSpec make_cell_activation_logic(const std::set> &activation_patterns, pool &supercell_aux) + RTLIL::SigSpec make_cell_activation_logic(const pool &activation_patterns, pool &supercell_aux) { RTLIL::Wire *all_cases_wire = module->addWire(NEW_ID, 0); @@ -1050,6 +1050,14 @@ struct ShareWorker // Setup and run // ------------- + void remove_cell(Cell *cell) + { + shareable_cells.erase(cell); + forbidden_controls_cache.erase(cell); + activation_patterns_cache.erase(cell); + module->remove(cell); + } + ShareWorker(ShareWorkerConfig config, RTLIL::Design *design, RTLIL::Module *module) : config(config), design(design), module(module), mi(module) { @@ -1097,7 +1105,7 @@ struct ShareWorker log(" Analyzing resource sharing options for %s:\n", log_id(cell)); - const std::set> &cell_activation_patterns = find_cell_activation_patterns(cell, " "); + const pool &cell_activation_patterns = find_cell_activation_patterns(cell, " "); RTLIL::SigSpec cell_activation_signals = bits_from_activation_patterns(cell_activation_patterns); if (cell_activation_patterns.empty()) { @@ -1106,7 +1114,7 @@ struct ShareWorker continue; } - if (cell_activation_patterns.count(std::pair())) { + if (cell_activation_patterns.count(ssc_pair_t())) { log(" Cell is always active. Therefore no sharing is possible.\n"); continue; } @@ -1130,7 +1138,7 @@ struct ShareWorker { log(" Analyzing resource sharing with %s:\n", log_id(other_cell)); - const std::set> &other_cell_activation_patterns = find_cell_activation_patterns(other_cell, " "); + const pool &other_cell_activation_patterns = find_cell_activation_patterns(other_cell, " "); RTLIL::SigSpec other_cell_activation_signals = bits_from_activation_patterns(other_cell_activation_patterns); if (other_cell_activation_patterns.empty()) { @@ -1140,7 +1148,7 @@ struct ShareWorker continue; } - if (other_cell_activation_patterns.count(std::pair())) { + if (other_cell_activation_patterns.count(ssc_pair_t())) { log(" Cell is always active. Therefore no sharing is possible.\n"); shareable_cells.erase(other_cell); continue; @@ -1149,8 +1157,8 @@ struct ShareWorker log(" Found %d activation_patterns using ctrl signal %s.\n", GetSize(other_cell_activation_patterns), log_signal(other_cell_activation_signals)); - const std::set &cell_forbidden_controls = find_forbidden_controls(cell); - const std::set &other_cell_forbidden_controls = find_forbidden_controls(other_cell); + const pool &cell_forbidden_controls = find_forbidden_controls(cell); + const pool &other_cell_forbidden_controls = find_forbidden_controls(other_cell); std::set union_forbidden_controls; union_forbidden_controls.insert(cell_forbidden_controls.begin(), cell_forbidden_controls.end()); @@ -1159,8 +1167,8 @@ struct ShareWorker if (!union_forbidden_controls.empty()) log(" Forbidden control signals for this pair of cells: %s\n", log_signal(union_forbidden_controls)); - std::set> filtered_cell_activation_patterns; - std::set> filtered_other_cell_activation_patterns; + pool filtered_cell_activation_patterns; + pool filtered_other_cell_activation_patterns; filter_activation_patterns(filtered_cell_activation_patterns, cell_activation_patterns, union_forbidden_controls); filter_activation_patterns(filtered_other_cell_activation_patterns, other_cell_activation_patterns, union_forbidden_controls); @@ -1305,11 +1313,11 @@ struct ShareWorker cells_to_remove.erase(other_cell); shareable_cells.insert(other_cell); for (auto cc : supercell_aux) - module->remove(cc); + remove_cell(cc); continue; } - std::set> supercell_activation_patterns; + pool supercell_activation_patterns; supercell_activation_patterns.insert(filtered_cell_activation_patterns.begin(), filtered_cell_activation_patterns.end()); supercell_activation_patterns.insert(filtered_other_cell_activation_patterns.begin(), filtered_other_cell_activation_patterns.end()); optimize_activation_patterns(supercell_activation_patterns); @@ -1337,7 +1345,7 @@ struct ShareWorker log("Removing %d cells in module %s:\n", GetSize(cells_to_remove), log_id(module)); for (auto c : cells_to_remove) { log(" Removing cell %s (%s).\n", log_id(c), log_id(c->type)); - module->remove(c); + remove_cell(c); } } From 397ae5b697e9923bb9d35df425370efd9357b127 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 02:46:59 +0100 Subject: [PATCH 207/492] gcc build fixes --- kernel/yosys.h | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/kernel/yosys.h b/kernel/yosys.h index 8ddd6f540..700a0603d 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -124,6 +125,8 @@ YOSYS_NAMESPACE_BEGIN +// Note: All headers included in hashlib.h must be included +// outside of YOSYS_NAMESPACE before this or bad things will happen. #ifdef HASHLIB_H # undef HASHLIB_H # include "kernel/hashlib.h" @@ -165,17 +168,19 @@ using RTLIL::Cell; using RTLIL::Module; using RTLIL::Design; -template<> struct hash_ops : hash_obj_ops {}; -template<> struct hash_ops : hash_obj_ops {}; -template<> struct hash_ops : hash_obj_ops {}; -template<> struct hash_ops : hash_obj_ops {}; -template<> struct hash_ops : hash_obj_ops {}; +namespace hashlib { + template<> struct hash_ops : hash_obj_ops {}; + template<> struct hash_ops : hash_obj_ops {}; + template<> struct hash_ops : hash_obj_ops {}; + template<> struct hash_ops : hash_obj_ops {}; + template<> struct hash_ops : hash_obj_ops {}; -template<> struct hash_ops : hash_obj_ops {}; -template<> struct hash_ops : hash_obj_ops {}; -template<> struct hash_ops : hash_obj_ops {}; -template<> struct hash_ops : hash_obj_ops {}; -template<> struct hash_ops : hash_obj_ops {}; + template<> struct hash_ops : hash_obj_ops {}; + template<> struct hash_ops : hash_obj_ops {}; + template<> struct hash_ops : hash_obj_ops {}; + template<> struct hash_ops : hash_obj_ops {}; + template<> struct hash_ops : hash_obj_ops {}; +} void memhasher_on(); void memhasher_off(); From 90bc71dd906935def78048e13e7c9f214af0486c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 03:11:50 +0100 Subject: [PATCH 208/492] dict/pool changes in ast --- frontends/ast/ast.cc | 4 ++++ frontends/ast/ast.h | 12 ++++++++---- frontends/ast/simplify.cc | 24 ++++++++++++------------ kernel/yosys.h | 6 ++++++ 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 8ef60079b..fbb726922 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -180,6 +180,10 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id) // (the optional child arguments make it easier to create AST trees) AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2) { + static unsigned int hashidx_count = 123456789; + hashidx_count = mkhash_xorshift(hashidx_count); + hashidx_ = hashidx_count; + this->type = type; filename = current_filename; linenum = get_line_num(); diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 1a7ac576b..180646267 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -142,6 +142,10 @@ namespace AST // The AST is built using instances of this struct struct AstNode { + // for dict<> and pool<> + unsigned int hashidx_; + unsigned int hash() const { return hashidx_; } + // this nodes type AstNodeType type; @@ -207,10 +211,10 @@ namespace AST AstNode *readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr); void expand_genblock(std::string index_var, std::string prefix, std::map &name_map); void replace_ids(const std::string &prefix, const std::map &rules); - void mem2reg_as_needed_pass1(std::map> &mem2reg_places, - std::map &mem2reg_flags, std::map &proc_flags, uint32_t &status_flags); - void mem2reg_as_needed_pass2(std::set &mem2reg_set, AstNode *mod, AstNode *block); - bool mem2reg_check(std::set &mem2reg_set); + void mem2reg_as_needed_pass1(dict> &mem2reg_places, + dict &mem2reg_flags, dict &proc_flags, uint32_t &status_flags); + void mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *block); + bool mem2reg_check(pool &mem2reg_set); void meminfo(int &mem_width, int &mem_size, int &addr_bits); // additional functionality for evaluating constant functions diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index b76701943..2ce2d57dc 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -67,12 +67,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (!flag_nomem2reg && !get_bool_attribute("\\nomem2reg")) { - std::map> mem2reg_places; - std::map mem2reg_candidates, dummy_proc_flags; + dict> mem2reg_places; + dict mem2reg_candidates, dummy_proc_flags; uint32_t flags = flag_mem2reg ? AstNode::MEM2REG_FL_ALL : 0; mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, dummy_proc_flags, flags); - std::set mem2reg_set; + pool mem2reg_set; for (auto &it : mem2reg_candidates) { AstNode *mem = it.first; @@ -2184,8 +2184,8 @@ void AstNode::replace_ids(const std::string &prefix, const std::map> &mem2reg_places, - std::map &mem2reg_candidates, AstNode *that) +static void mark_memories_assign_lhs_complex(dict> &mem2reg_places, + dict &mem2reg_candidates, AstNode *that) { for (auto &child : that->children) mark_memories_assign_lhs_complex(mem2reg_places, mem2reg_candidates, child); @@ -2199,8 +2199,8 @@ static void mark_memories_assign_lhs_complex(std::map> &mem2reg_places, - std::map &mem2reg_candidates, std::map &proc_flags, uint32_t &flags) +void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg_places, + dict &mem2reg_candidates, dict &proc_flags, uint32_t &flags) { uint32_t children_flags = 0; int ignore_children_counter = 0; @@ -2262,7 +2262,7 @@ void AstNode::mem2reg_as_needed_pass1(std::map> if (type == AST_MODULE && get_bool_attribute("\\mem2reg")) children_flags |= AstNode::MEM2REG_FL_ALL; - std::map *proc_flags_p = NULL; + dict *proc_flags_p = NULL; if (type == AST_ALWAYS) { int count_edge_events = 0; @@ -2271,12 +2271,12 @@ void AstNode::mem2reg_as_needed_pass1(std::map> count_edge_events++; if (count_edge_events != 1) children_flags |= AstNode::MEM2REG_FL_ASYNC; - proc_flags_p = new std::map; + proc_flags_p = new dict; } if (type == AST_INITIAL) { children_flags |= AstNode::MEM2REG_FL_INIT; - proc_flags_p = new std::map; + proc_flags_p = new dict; } uint32_t backup_flags = flags; @@ -2300,7 +2300,7 @@ void AstNode::mem2reg_as_needed_pass1(std::map> } } -bool AstNode::mem2reg_check(std::set &mem2reg_set) +bool AstNode::mem2reg_check(pool &mem2reg_set) { if (type != AST_IDENTIFIER || !id2ast || !mem2reg_set.count(id2ast)) return false; @@ -2312,7 +2312,7 @@ bool AstNode::mem2reg_check(std::set &mem2reg_set) } // actually replace memories with registers -void AstNode::mem2reg_as_needed_pass2(std::set &mem2reg_set, AstNode *mod, AstNode *block) +void AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *block) { if (type == AST_BLOCK) block = this; diff --git a/kernel/yosys.h b/kernel/yosys.h index 700a0603d..c0004abce 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -159,6 +159,10 @@ namespace RTLIL { struct Monitor; } +namespace AST { + struct AstNode; +} + using RTLIL::IdString; using RTLIL::Const; using RTLIL::SigBit; @@ -174,12 +178,14 @@ namespace hashlib { template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; + template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; template<> struct hash_ops : hash_obj_ops {}; + template<> struct hash_ops : hash_obj_ops {}; } void memhasher_on(); From 662cb549e4e11d15b9c1c7e4d3944a05dab2447f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 03:49:45 +0100 Subject: [PATCH 209/492] Added newline support to Pass::call() parser --- kernel/register.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/kernel/register.cc b/kernel/register.cc index 2927a333e..7086e1424 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -182,6 +182,18 @@ void Pass::call(RTLIL::Design *design, std::string command) call(design, "clean -purge"); } else args.push_back(tok); + bool found_nl = false; + for (auto c : cmd_buf) { + if (c == ' ' || c == '\t') + continue; + if (c == '\r' || c == '\n') + found_nl = true; + break; + } + if (found_nl) { + call(design, args); + args.clear(); + } tok = next_token(cmd_buf, " \t\r\n"); } From 7d843adef98ec051acc64f4a04c925c468b562c2 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 04:06:52 +0100 Subject: [PATCH 210/492] dict/pool changes in opt_clean --- kernel/sigtools.h | 9 +++++++++ passes/opt/opt_clean.cc | 10 +++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/kernel/sigtools.h b/kernel/sigtools.h index 5281b7a45..c38736e70 100644 --- a/kernel/sigtools.h +++ b/kernel/sigtools.h @@ -195,6 +195,15 @@ struct SigSet } } + void find(RTLIL::SigSpec sig, pool &result) + { + for (auto &bit : sig) + if (bit.wire != NULL) { + auto &data = bits[bit]; + result.insert(data.begin(), data.end()); + } + } + std::set find(RTLIL::SigSpec sig) { std::set result; diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index b9ff5d302..aabdbf013 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -53,7 +53,7 @@ void rmunused_module_cells(RTLIL::Module *module, bool verbose) for (auto &it : module->wires_) { RTLIL::Wire *wire = it.second; if (wire->port_output || wire->get_bool_attribute("\\keep")) { - std::set cell_list; + pool cell_list; wire2driver.find(sigmap(wire), cell_list); for (auto cell : cell_list) queue.insert(cell); @@ -68,7 +68,7 @@ void rmunused_module_cells(RTLIL::Module *module, bool verbose) for (auto cell : queue) { for (auto &it : cell->connections()) { if (!ct.cell_output(cell->type, it.first)) { - std::set cell_list; + pool cell_list; wire2driver.find(sigmap(it.second), cell_list); for (auto c : cell_list) { if (unused.count(c)) @@ -97,7 +97,7 @@ int count_nontrivial_wire_attrs(RTLIL::Wire *w) return count; } -bool compare_signals(RTLIL::SigBit &s1, RTLIL::SigBit &s2, SigPool ®s, SigPool &conns, std::set &direct_wires) +bool compare_signals(RTLIL::SigBit &s1, RTLIL::SigBit &s2, SigPool ®s, SigPool &conns, pool &direct_wires) { RTLIL::Wire *w1 = s1.wire; RTLIL::Wire *w2 = s2.wire; @@ -161,8 +161,8 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } SigMap assign_map(module); - std::set direct_sigs; - std::set direct_wires; + pool direct_sigs; + pool direct_wires; for (auto &it : module->cells_) { RTLIL::Cell *cell = it.second; if (ct_all.cell_known(cell->type)) From 33e25394b447eda249cc9cf7c114093f3069fb62 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 04:15:48 +0100 Subject: [PATCH 211/492] Fixed comment parsing in Pass::call() --- kernel/register.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/kernel/register.cc b/kernel/register.cc index 7086e1424..56dc695aa 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -150,7 +150,7 @@ void Pass::call(RTLIL::Design *design, std::string command) std::string cmd_buf = command; std::string tok = next_token(cmd_buf, " \t\r\n"); - if (tok.empty() || tok[0] == '#') + if (tok.empty()) return; if (tok[0] == '!') { @@ -166,8 +166,13 @@ void Pass::call(RTLIL::Design *design, std::string command) } while (!tok.empty()) { - if (tok == "#") - break; + if (tok == "#") { + int stop; + for (stop = 0; stop < GetSize(cmd_buf); stop++) + if (cmd_buf[stop] == '\r' || cmd_buf[stop] == '\n') + break; + cmd_buf = cmd_buf.substr(stop); + } else if (tok.back() == ';') { int num_semikolon = 0; while (!tok.empty() && tok.back() == ';') From 3ff0d04555c4467a2d9bcd5e754d82ede5bf84dd Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 05:10:19 +0100 Subject: [PATCH 212/492] Cleanups in opt_clean --- passes/opt/opt_clean.cc | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index aabdbf013..c5b25816c 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -347,16 +347,16 @@ struct OptCleanPass : public Pass { ct_reg.setup_internals_mem(); ct_reg.setup_stdcells_mem(); - for (auto &mod_it : design->modules_) { - if (!design->selected_whole_module(mod_it.first)) { - if (design->selected(mod_it.second)) - log("Skipping module %s as it is only partially selected.\n", id2cstr(mod_it.second->name)); + for (auto mod : design->modules()) { + if (!design->selected_whole_module(mod->name)) { + if (design->selected(mod)) + log("Skipping module %s as it is only partially selected.\n", id2cstr(mod->name)); continue; } - if (mod_it.second->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", mod_it.second->name.c_str()); + if (!mod->processes.empty()) { + log("Skipping module %s as it contains processes.\n", mod->name.c_str()); } else { - rmunused_module(mod_it.second, purge_mode, true); + rmunused_module(mod, purge_mode, true); } } @@ -411,11 +411,11 @@ struct CleanPass : public Pass { count_rm_cells = 0; count_rm_wires = 0; - for (auto &mod_it : design->modules_) { - if (design->selected_whole_module(mod_it.first) && mod_it.second->processes.size() == 0) + for (auto mod : design->modules()) { + if (design->selected_whole_module(mod->name) && mod->processes.empty()) do { design->scratchpad_unset("opt.did_something"); - rmunused_module(mod_it.second, purge_mode, false); + rmunused_module(mod, purge_mode, false); } while (design->scratchpad_get_bool("opt.did_something")); } From ecd64182c5a3689ef293bccf032e1d7eecada91a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 13:33:33 +0100 Subject: [PATCH 213/492] Added "yosys -X" --- kernel/driver.cc | 8 +++- kernel/log.cc | 95 ++++++++++++++++++++++++++++++++++++++++++++++++ kernel/log.h | 1 + kernel/rtlil.cc | 37 +++++++++++++++++++ kernel/rtlil.h | 11 ++++++ kernel/yosys.cc | 1 + kernel/yosys.h | 1 + 7 files changed, 153 insertions(+), 1 deletion(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index 9a81d8a48..cdf784602 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -151,6 +151,9 @@ int main(int argc, char **argv) printf(" -m module_file\n"); printf(" load the specified module (aka plugin)\n"); printf("\n"); + printf(" -X\n"); + printf(" enable tracing of core data structure changes. for debugging\n"); + printf("\n"); printf(" -M\n"); printf(" will slightly randomize allocated pointer addresses. for debugging\n"); printf("\n"); @@ -177,13 +180,16 @@ int main(int argc, char **argv) } int opt; - while ((opt = getopt(argc, argv, "MAQTVSm:f:Hh:b:o:p:l:qv:tds:c:")) != -1) + while ((opt = getopt(argc, argv, "MXAQTVSm:f:Hh:b:o:p:l:qv:tds:c:")) != -1) { switch (opt) { case 'M': memhasher_on(); break; + case 'X': + yosys_xtrace++; + break; case 'A': call_abort = true; break; diff --git a/kernel/log.cc b/kernel/log.cc index 5b18e3d6c..b984f0112 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -25,6 +25,10 @@ # include #endif +#ifdef __linux__ +# include +#endif + #include #include #include @@ -243,6 +247,97 @@ void log_pop() log_flush(); } +void log_backtrace(const char *prefix, int levels) +{ +#ifdef __linux__ + if (levels <= 0) return; + + Dl_info dli; + void *p; + + if ((p = __builtin_extract_return_addr(__builtin_return_address(0))) && dladdr(p, &dli)) { + log("%sframe #1: %p %s(%p) %s(%p)\n", prefix, p, dli.dli_fname, dli.dli_fbase, dli.dli_sname, dli.dli_saddr); + } else { + log("%sframe #1: ---\n", prefix); + return; + } + + if (levels <= 1) return; + + if ((p = __builtin_extract_return_addr(__builtin_return_address(1))) && dladdr(p, &dli)) { + log("%sframe #2: %p %s(%p) %s(%p)\n", prefix, p, dli.dli_fname, dli.dli_fbase, dli.dli_sname, dli.dli_saddr); + } else { + log("%sframe #2: ---\n", prefix); + return; + } + + if (levels <= 2) return; + + if ((p = __builtin_extract_return_addr(__builtin_return_address(2))) && dladdr(p, &dli)) { + log("%sframe #3: %p %s(%p) %s(%p)\n", prefix, p, dli.dli_fname, dli.dli_fbase, dli.dli_sname, dli.dli_saddr); + } else { + log("%sframe #3: ---\n", prefix); + return; + } + + if (levels <= 3) return; + + if ((p = __builtin_extract_return_addr(__builtin_return_address(3))) && dladdr(p, &dli)) { + log("%sframe #4: %p %s(%p) %s(%p)\n", prefix, p, dli.dli_fname, dli.dli_fbase, dli.dli_sname, dli.dli_saddr); + } else { + log("%sframe #4: ---\n", prefix); + return; + } + + if (levels <= 4) return; + + if ((p = __builtin_extract_return_addr(__builtin_return_address(4))) && dladdr(p, &dli)) { + log("%sframe #5: %p %s(%p) %s(%p)\n", prefix, p, dli.dli_fname, dli.dli_fbase, dli.dli_sname, dli.dli_saddr); + } else { + log("%sframe #5: ---\n", prefix); + return; + } + + if (levels <= 5) return; + + if ((p = __builtin_extract_return_addr(__builtin_return_address(5))) && dladdr(p, &dli)) { + log("%sframe #6: %p %s(%p) %s(%p)\n", prefix, p, dli.dli_fname, dli.dli_fbase, dli.dli_sname, dli.dli_saddr); + } else { + log("%sframe #6: ---\n", prefix); + return; + } + + if (levels <= 6) return; + + if ((p = __builtin_extract_return_addr(__builtin_return_address(6))) && dladdr(p, &dli)) { + log("%sframe #7: %p %s(%p) %s(%p)\n", prefix, p, dli.dli_fname, dli.dli_fbase, dli.dli_sname, dli.dli_saddr); + } else { + log("%sframe #7: ---\n", prefix); + return; + } + + if (levels <= 7) return; + + if ((p = __builtin_extract_return_addr(__builtin_return_address(7))) && dladdr(p, &dli)) { + log("%sframe #8: %p %s(%p) %s(%p)\n", prefix, p, dli.dli_fname, dli.dli_fbase, dli.dli_sname, dli.dli_saddr); + } else { + log("%sframe #8: ---\n", prefix); + return; + } + + if (levels <= 8) return; + + if ((p = __builtin_extract_return_addr(__builtin_return_address(8))) && dladdr(p, &dli)) { + log("%sframe #9: %p %s(%p) %s(%p)\n", prefix, p, dli.dli_fname, dli.dli_fbase, dli.dli_sname, dli.dli_saddr); + } else { + log("%sframe #9: ---\n", prefix); + return; + } + + if (levels <= 9) return; +#endif +} + void log_reset_stack() { while (header_count.size() > 1) diff --git a/kernel/log.h b/kernel/log.h index 9bb2b3621..8096758f6 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -65,6 +65,7 @@ void log_spacer(); void log_push(); void log_pop(); +void log_backtrace(const char *prefix, int levels); void log_reset_stack(); void log_flush(); diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index f25df175d..912df7903 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -269,6 +269,11 @@ void RTLIL::Design::add(RTLIL::Module *module) for (auto mon : monitors) mon->notify_module_add(module); + + if (yosys_xtrace) { + log("#X# New Module: %s\n", log_id(module)); + log_backtrace("-X- ", yosys_xtrace-1); + } } RTLIL::Module *RTLIL::Design::addModule(RTLIL::IdString name) @@ -284,6 +289,11 @@ RTLIL::Module *RTLIL::Design::addModule(RTLIL::IdString name) for (auto mon : monitors) mon->notify_module_add(module); + if (yosys_xtrace) { + log("#X# New Module: %s\n", log_id(module)); + log_backtrace("-X- ", yosys_xtrace-1); + } + return module; } @@ -353,6 +363,11 @@ void RTLIL::Design::remove(RTLIL::Module *module) for (auto mon : monitors) mon->notify_module_del(module); + if (yosys_xtrace) { + log("#X# Remove Module: %s\n", log_id(module)); + log_backtrace("-X- ", yosys_xtrace-1); + } + log_assert(modules_.at(module->name) == module); modules_.erase(module->name); delete module; @@ -1283,6 +1298,11 @@ void RTLIL::Module::connect(const RTLIL::SigSig &conn) for (auto mon : design->monitors) mon->notify_connect(this, conn); + if (yosys_xtrace) { + log("#X# Connect (SigSig) in %s: %s = %s (%d bits)\n", log_id(this), log_signal(conn.first), log_signal(conn.second), GetSize(conn.first)); + log_backtrace("-X- ", yosys_xtrace-1); + } + connections_.push_back(conn); } @@ -1300,6 +1320,13 @@ void RTLIL::Module::new_connections(const std::vector &new_conn) for (auto mon : design->monitors) mon->notify_connect(this, new_conn); + if (yosys_xtrace) { + log("#X# New connections vector in %s:\n", log_id(this)); + for (auto &conn: new_conn) + log("#X# %s = %s (%d bits)\n", log_signal(conn.first), log_signal(conn.second), GetSize(conn.first)); + log_backtrace("-X- ", yosys_xtrace-1); + } + connections_ = new_conn; } @@ -1795,6 +1822,11 @@ void RTLIL::Cell::unsetPort(RTLIL::IdString portname) for (auto mon : module->design->monitors) mon->notify_connect(this, conn_it->first, conn_it->second, signal); + if (yosys_xtrace) { + log("#X# Unconnect %s.%s.%s\n", log_id(this->module), log_id(this), log_id(portname)); + log_backtrace("-X- ", yosys_xtrace-1); + } + connections_.erase(conn_it); } } @@ -1816,6 +1848,11 @@ void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) for (auto mon : module->design->monitors) mon->notify_connect(this, conn_it->first, conn_it->second, signal); + if (yosys_xtrace) { + log("#X# Connect %s.%s.%s = %s (%d)\n", log_id(this->module), log_id(this), log_id(portname), log_signal(signal), GetSize(signal)); + log_backtrace("-X- ", yosys_xtrace-1); + } + conn_it->second = signal; } diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 25477d02e..bb9e85d93 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -120,6 +120,12 @@ namespace RTLIL global_id_storage_.at(idx) = strdup(p); global_id_index_[global_id_storage_.at(idx)] = idx; global_refcount_storage_.at(idx)++; + + if (yosys_xtrace) { + log("#X# New IdString '%s' with index %d.\n", p, idx); + log_backtrace("-X- ", yosys_xtrace-1); + } + return idx; } @@ -135,6 +141,11 @@ namespace RTLIL if (--global_refcount_storage_.at(idx) != 0) return; + if (yosys_xtrace) { + log("#X# Removed IdString '%s' with index %d.\n", global_id_storage_.at(idx), idx); + log_backtrace("-X- ", yosys_xtrace-1); + } + global_id_index_.erase(global_id_storage_.at(idx)); free(global_id_storage_.at(idx)); global_id_storage_.at(idx) = nullptr; diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 0faca8d51..6bc8dd0bb 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -49,6 +49,7 @@ YOSYS_NAMESPACE_BEGIN int autoidx = 1; +int yosys_xtrace = 0; RTLIL::Design *yosys_design = NULL; #ifdef YOSYS_ENABLE_TCL diff --git a/kernel/yosys.h b/kernel/yosys.h index c0004abce..a4836f35a 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -210,6 +210,7 @@ template int GetSize(const T &obj) { return obj.size(); } int GetSize(RTLIL::Wire *wire); extern int autoidx; +extern int yosys_xtrace; YOSYS_NAMESPACE_END From 0bb6b24c117fa685dce34abf82cb0f9ef73a7661 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 14:30:33 +0100 Subject: [PATCH 214/492] Added global yosys_celltypes --- frontends/ast/ast.cc | 2 +- kernel/celltypes.h | 93 ++++++++++++++++++++++++++------------------ kernel/yosys.cc | 9 +++++ 3 files changed, 65 insertions(+), 39 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index fbb726922..68b3327f9 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -26,7 +26,7 @@ * */ -#include "kernel/log.h" +#include "kernel/yosys.h" #include "libs/sha1/sha1.h" #include "ast.h" diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 32e144194..3a56de2f7 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -96,88 +96,102 @@ struct CellTypes "$logic_and", "$logic_or", "$concat", "$macc" }; + IdString A = "\\A", B = "\\B", S = "\\S", Y = "\\Y"; + IdString P = "\\P", G = "\\G", C = "\\C", X = "\\X"; + IdString BI = "\\BI", CI = "\\CI", CO = "\\CO", EN = "\\EN"; + for (auto type : unary_ops) - setup_type(type, {"\\A"}, {"\\Y"}, true); + setup_type(type, {A}, {Y}, true); for (auto type : binary_ops) - setup_type(type, {"\\A", "\\B"}, {"\\Y"}, true); + setup_type(type, {A, B}, {Y}, true); for (auto type : std::vector({"$mux", "$pmux"})) - setup_type(type, {"\\A", "\\B", "\\S"}, {"\\Y"}, true); + setup_type(type, {A, B, S}, {Y}, true); - setup_type("$lcu", {"\\P", "\\G", "\\CI"}, {"\\CO"}, true); - setup_type("$alu", {"\\A", "\\B", "\\CI", "\\BI"}, {"\\X", "\\Y", "\\CO"}, true); - setup_type("$fa", {"\\A", "\\B", "\\C"}, {"\\X", "\\Y"}, true); + setup_type("$lcu", {P, G, CI}, {CO}, true); + setup_type("$alu", {A, B, CI, BI}, {X, Y, CO}, true); + setup_type("$fa", {A, B, C}, {X, Y}, true); - setup_type("$assert", {"\\A", "\\EN"}, pool(), true); + setup_type("$assert", {A, EN}, pool(), true); } void setup_internals_mem() { - setup_type("$sr", {"\\SET", "\\CLR"}, {"\\Q"}); - setup_type("$dff", {"\\CLK", "\\D"}, {"\\Q"}); - setup_type("$dffe", {"\\CLK", "\\EN", "\\D"}, {"\\Q"}); - setup_type("$dffsr", {"\\CLK", "\\SET", "\\CLR", "\\D"}, {"\\Q"}); - setup_type("$adff", {"\\CLK", "\\ARST", "\\D"}, {"\\Q"}); - setup_type("$dlatch", {"\\EN", "\\D"}, {"\\Q"}); - setup_type("$dlatchsr", {"\\EN", "\\SET", "\\CLR", "\\D"}, {"\\Q"}); + IdString SET = "\\SET", CLR = "\\CLR", CLK = "\\CLK", ARST = "\\ARST", EN = "\\EN"; + IdString Q = "\\Q", D = "\\D", ADDR = "\\ADDR", DATA = "\\DATA"; + IdString RD_CLK = "\\RD_CLK", RD_ADDR = "\\RD_ADDR", WR_CLK = "\\WR_CLK", WR_EN = "\\WR_EN"; + IdString WR_ADDR = "\\WR_ADDR", WR_DATA = "\\WR_DATA", RD_DATA = "\\RD_DATA"; + IdString CTRL_IN = "\\CTRL_IN", CTRL_OUT = "\\CTRL_OUT"; - setup_type("$memrd", {"\\CLK", "\\ADDR"}, {"\\DATA"}); - setup_type("$memwr", {"\\CLK", "\\EN", "\\ADDR", "\\DATA"}, pool()); - setup_type("$mem", {"\\RD_CLK", "\\RD_ADDR", "\\WR_CLK", "\\WR_EN", "\\WR_ADDR", "\\WR_DATA"}, {"\\RD_DATA"}); + setup_type("$sr", {SET, CLR}, {Q}); + setup_type("$dff", {CLK, D}, {Q}); + setup_type("$dffe", {CLK, EN, D}, {Q}); + setup_type("$dffsr", {CLK, SET, CLR, D}, {Q}); + setup_type("$adff", {CLK, ARST, D}, {Q}); + setup_type("$dlatch", {EN, D}, {Q}); + setup_type("$dlatchsr", {EN, SET, CLR, D}, {Q}); - setup_type("$fsm", {"\\CLK", "\\ARST", "\\CTRL_IN"}, {"\\CTRL_OUT"}); + setup_type("$memrd", {CLK, ADDR}, {DATA}); + setup_type("$memwr", {CLK, EN, ADDR, DATA}, pool()); + setup_type("$mem", {RD_CLK, RD_ADDR, WR_CLK, WR_EN, WR_ADDR, WR_DATA}, {RD_DATA}); + + setup_type("$fsm", {CLK, ARST, CTRL_IN}, {CTRL_OUT}); } void setup_stdcells() { - setup_type("$_BUF_", {"\\A"}, {"\\Y"}, true); - setup_type("$_NOT_", {"\\A"}, {"\\Y"}, true); - setup_type("$_AND_", {"\\A", "\\B"}, {"\\Y"}, true); - setup_type("$_NAND_", {"\\A", "\\B"}, {"\\Y"}, true); - setup_type("$_OR_", {"\\A", "\\B"}, {"\\Y"}, true); - setup_type("$_NOR_", {"\\A", "\\B"}, {"\\Y"}, true); - setup_type("$_XOR_", {"\\A", "\\B"}, {"\\Y"}, true); - setup_type("$_XNOR_", {"\\A", "\\B"}, {"\\Y"}, true); - setup_type("$_MUX_", {"\\A", "\\B", "\\S"}, {"\\Y"}, true); - setup_type("$_AOI3_", {"\\A", "\\B", "\\C"}, {"\\Y"}, true); - setup_type("$_OAI3_", {"\\A", "\\B", "\\C"}, {"\\Y"}, true); - setup_type("$_AOI4_", {"\\A", "\\B", "\\C", "\\D"}, {"\\Y"}, true); - setup_type("$_OAI4_", {"\\A", "\\B", "\\C", "\\D"}, {"\\Y"}, true); + IdString A = "\\A", B = "\\B", C = "\\C", D = "\\D", S = "\\S", Y = "\\Y"; + setup_type("$_BUF_", {A}, {Y}, true); + setup_type("$_NOT_", {A}, {Y}, true); + setup_type("$_AND_", {A, B}, {Y}, true); + setup_type("$_NAND_", {A, B}, {Y}, true); + setup_type("$_OR_", {A, B}, {Y}, true); + setup_type("$_NOR_", {A, B}, {Y}, true); + setup_type("$_XOR_", {A, B}, {Y}, true); + setup_type("$_XNOR_", {A, B}, {Y}, true); + setup_type("$_MUX_", {A, B, S}, {Y}, true); + setup_type("$_AOI3_", {A, B, C}, {Y}, true); + setup_type("$_OAI3_", {A, B, C}, {Y}, true); + setup_type("$_AOI4_", {A, B, C, D}, {Y}, true); + setup_type("$_OAI4_", {A, B, C, D}, {Y}, true); } void setup_stdcells_mem() { + IdString S = "\\S", R = "\\R", C = "\\C"; + IdString D = "\\D", Q = "\\Q", E = "\\E"; + std::vector list_np = {'N', 'P'}, list_01 = {'0', '1'}; for (auto c1 : list_np) for (auto c2 : list_np) - setup_type(stringf("$_SR_%c%c_", c1, c2), {"\\S", "\\R"}, {"\\Q"}); + setup_type(stringf("$_SR_%c%c_", c1, c2), {S, R}, {Q}); for (auto c1 : list_np) - setup_type(stringf("$_DFF_%c_", c1), {"\\C", "\\D"}, {"\\Q"}); + setup_type(stringf("$_DFF_%c_", c1), {C, D}, {Q}); for (auto c1 : list_np) for (auto c2 : list_np) - setup_type(stringf("$_DFFE_%c%c_", c1, c2), {"\\C", "\\D", "\\E"}, {"\\Q"}); + setup_type(stringf("$_DFFE_%c%c_", c1, c2), {C, D, E}, {Q}); for (auto c1 : list_np) for (auto c2 : list_np) for (auto c3 : list_01) - setup_type(stringf("$_DFF_%c%c%c_", c1, c2, c3), {"\\C", "\\R", "\\D"}, {"\\Q"}); + setup_type(stringf("$_DFF_%c%c%c_", c1, c2, c3), {C, R, D}, {Q}); for (auto c1 : list_np) for (auto c2 : list_np) for (auto c3 : list_np) - setup_type(stringf("$_DFFSR_%c%c%c_", c1, c2, c3), {"\\C", "\\S", "\\R", "\\D"}, {"\\Q"}); + setup_type(stringf("$_DFFSR_%c%c%c_", c1, c2, c3), {C, S, R, D}, {Q}); for (auto c1 : list_np) - setup_type(stringf("$_DLATCH_%c_", c1), {"\\E", "\\D"}, {"\\Q"}); + setup_type(stringf("$_DLATCH_%c_", c1), {E, D}, {Q}); for (auto c1 : list_np) for (auto c2 : list_np) for (auto c3 : list_np) - setup_type(stringf("$_DLATCHSR_%c%c%c_", c1, c2, c3), {"\\E", "\\S", "\\R", "\\D"}, {"\\Q"}); + setup_type(stringf("$_DLATCHSR_%c%c%c_", c1, c2, c3), {E, S, R, D}, {Q}); } void clear() @@ -368,6 +382,9 @@ struct CellTypes } }; +// initialized by yosys_setup() +extern CellTypes yosys_celltypes; + YOSYS_NAMESPACE_END #endif diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 6bc8dd0bb..444bdb1d2 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -18,6 +18,7 @@ */ #include "kernel/yosys.h" +#include "kernel/celltypes.h" #ifdef YOSYS_ENABLE_READLINE # include @@ -51,6 +52,7 @@ YOSYS_NAMESPACE_BEGIN int autoidx = 1; int yosys_xtrace = 0; RTLIL::Design *yosys_design = NULL; +CellTypes yosys_celltypes; #ifdef YOSYS_ENABLE_TCL Tcl_Interp *yosys_tcl_interp = NULL; @@ -378,8 +380,14 @@ int GetSize(RTLIL::Wire *wire) void yosys_setup() { + // if there are already IdString objects then we have a global initialization order bug + IdString empty_id; + log_assert(empty_id.index_ == 0); + IdString::get_reference(empty_id.index_); + Pass::init_register(); yosys_design = new RTLIL::Design; + yosys_celltypes.setup(); log_push(); } @@ -397,6 +405,7 @@ void yosys_shutdown() log_files.clear(); Pass::done_register(); + yosys_celltypes.clear(); #ifdef YOSYS_ENABLE_TCL if (yosys_tcl_interp != NULL) { From 7a4d5d1c0fb78d49163160bfabb8cd1f5d1a2899 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 15:17:40 +0100 Subject: [PATCH 215/492] Less verbose ABC output --- kernel/yosys.cc | 2 -- passes/abc/abc.cc | 73 ++++++++++++++++++++++++++++++----------- passes/abc/blifparse.cc | 3 +- 3 files changed, 55 insertions(+), 23 deletions(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 444bdb1d2..fa9fffa62 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -360,7 +360,6 @@ void remove_directory(std::string dirname) if (strcmp(namelist[i]->d_name, ".") && strcmp(namelist[i]->d_name, "..")) { std::string buffer = stringf("%s/%s", dirname.c_str(), namelist[i]->d_name); if (!stat(buffer.c_str(), &stbuf) && S_ISREG(stbuf.st_mode)) { - log("Removing `%s'.\n", buffer.c_str()); remove(buffer.c_str()); } else remove_directory(buffer); @@ -368,7 +367,6 @@ void remove_directory(std::string dirname) free(namelist[i]); } free(namelist); - log("Removing `%s'.\n", dirname.c_str()); rmdir(dirname.c_str()); #endif } diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 844d5783c..9ee8aa1b0 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -29,15 +29,15 @@ // Kahn, Arthur B. (1962), "Topological sorting of large networks", Communications of the ACM 5 (11): 558–562, doi:10.1145/368996.369025 // http://en.wikipedia.org/wiki/Topological_sorting -#define ABC_COMMAND_LIB "strash; scorr -v; ifraig -v; retime -v {D}; strash; dch -vf; map -v {D}" -#define ABC_COMMAND_CTR "strash; scorr -v; ifraig -v; retime -v {D}; strash; dch -vf; map -v {D}; buffer -v; upsize -v {D}; dnsize -v {D}; stime -p" -#define ABC_COMMAND_LUT "strash; scorr -v; ifraig -v; retime -v; strash; dch -vf; if -v" -#define ABC_COMMAND_DFL "strash; scorr -v; ifraig -v; retime -v; strash; dch -vf; map -v" +#define ABC_COMMAND_LIB "strash; scorr; ifraig; retime {D}; strash; dchf; map {D}" +#define ABC_COMMAND_CTR "strash; scorr; ifraig; retime {D}; strash; dchf; map {D}; buffer; upsize {D}; dnsize {D}; stime -p" +#define ABC_COMMAND_LUT "strash; scorr; ifraig; retime; strash; dch -f; if" +#define ABC_COMMAND_DFL "strash; scorr; ifraig; retime; strash; dch -f; map" -#define ABC_FAST_COMMAND_LIB "retime -v {D}; map -v {D}" -#define ABC_FAST_COMMAND_CTR "retime -v {D}; map -v {D}; buffer -v; upsize -v {D}; dnsize -v {D}; stime -p" -#define ABC_FAST_COMMAND_LUT "retime -v; if -v" -#define ABC_FAST_COMMAND_DFL "retime -v; map -v" +#define ABC_FAST_COMMAND_LIB "retime {D}; map {D}" +#define ABC_FAST_COMMAND_CTR "retime {D}; map {D}; buffer; upsize {D}; dnsize {D}; stime -p" +#define ABC_FAST_COMMAND_LUT "retime; if" +#define ABC_FAST_COMMAND_DFL "retime; map" #include "kernel/register.h" #include "kernel/sigtools.h" @@ -479,8 +479,6 @@ std::string add_echos_to_abc_cmd(std::string str) if (str[i] == ';') { while (i+1 < str.size() && str[i+1] == ' ') i++; - if (!new_str.empty()) - new_str += "echo; "; new_str += "echo + " + token + " " + token + " "; token.clear(); } @@ -488,7 +486,7 @@ std::string add_echos_to_abc_cmd(std::string str) if (!token.empty()) { if (!new_str.empty()) - new_str += "echo; echo + " + token + "; "; + new_str += "echo + " + token + "; "; new_str += token; } @@ -514,13 +512,38 @@ std::string fold_abc_cmd(std::string str) return new_str; } +std::string replace_tempdir(std::string text, std::string tempdir_name, bool show_tempdir) +{ + if (show_tempdir) + return text; + + while (1) { + size_t pos = text.find(tempdir_name); + if (pos == std::string::npos) + break; + text = text.substr(0, pos) + "" + text.substr(pos + GetSize(tempdir_name)); + } + + std::string selfdir_name = proc_self_dirname(); + while (1) { + size_t pos = text.find(selfdir_name); + if (pos == std::string::npos) + break; + text = text.substr(0, pos) + "/" + text.substr(pos + GetSize(selfdir_name)); + } + + return text; +} + struct abc_output_filter { bool got_cr; int escape_seq_state; std::string linebuf; + std::string tempdir_name; + bool show_tempdir; - abc_output_filter() + abc_output_filter(std::string tempdir_name, bool show_tempdir) : tempdir_name(tempdir_name), show_tempdir(show_tempdir) { got_cr = false; escape_seq_state = 0; @@ -547,7 +570,7 @@ struct abc_output_filter return; } if (ch == '\n') { - log("ABC: %s\n", linebuf.c_str()); + log("ABC: %s\n", replace_tempdir(linebuf, tempdir_name, show_tempdir).c_str()); got_cr = false, linebuf.clear(); return; } @@ -565,7 +588,7 @@ struct abc_output_filter void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, std::string liberty_file, std::string constr_file, bool cleanup, int lut_mode, bool dff_mode, std::string clk_str, - bool keepff, std::string delay_target, bool fast_mode, const std::vector &cells) + bool keepff, std::string delay_target, bool fast_mode, const std::vector &cells, bool show_tempdir) { module = current_module; map_autoidx = autoidx++; @@ -588,7 +611,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (!cleanup) tempdir_name[0] = tempdir_name[4] = '_'; tempdir_name = make_temp_dir(tempdir_name); - log_header("Extracting gate netlist of module `%s' to `%s/input.blif'..\n", module->name.c_str(), tempdir_name.c_str()); + log_header("Extracting gate netlist of module `%s' to `%s/input.blif'..\n", + module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str()); std::string abc_script = stringf("read_blif %s/input.blif; ", tempdir_name.c_str()); @@ -833,9 +857,9 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin } buffer = stringf("%s -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str()); - log("Running ABC command: %s\n", buffer.c_str()); + log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str()); - abc_output_filter filt; + abc_output_filter filt(tempdir_name, show_tempdir); int ret = run_command(buffer, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1)); if (ret != 0) log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); @@ -1036,7 +1060,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (cleanup) { - log_header("Removing temp directory `%s':\n", tempdir_name.c_str()); + log("Removing temp directory.\n"); remove_directory(tempdir_name); } @@ -1135,6 +1159,10 @@ struct AbcPass : public Pass { log(" when this option is used, the temporary files created by this pass\n"); log(" are not removed. this is useful for debugging.\n"); log("\n"); + log(" -showtmp\n"); + log(" print the temp dir name in log. usually this is suppressed so that the\n"); + log(" command output is identical across runs.\n"); + log("\n"); log(" -markgroups\n"); log(" set a 'abcgroup' attribute on all objects created by ABC. The value of\n"); log(" this attribute is a unique integer for each ABC process started. This\n"); @@ -1157,6 +1185,7 @@ struct AbcPass : public Pass { std::string exe_file = proc_self_dirname() + "yosys-abc"; std::string script_file, liberty_file, constr_file, clk_str, delay_target; bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; + bool show_tempdir = false; int lut_mode = 0; markgroups = false; @@ -1224,6 +1253,10 @@ struct AbcPass : public Pass { cleanup = false; continue; } + if (arg == "-showtmp") { + show_tempdir = true; + continue; + } if (arg == "-markgroups") { markgroups = true; continue; @@ -1241,7 +1274,7 @@ struct AbcPass : public Pass { if (mod->processes.size() > 0) log("Skipping module %s as it contains processes.\n", log_id(mod)); else if (!dff_mode || !clk_str.empty()) - abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, dff_mode, clk_str, keepff, delay_target, fast_mode, mod->selected_cells()); + abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, dff_mode, clk_str, keepff, delay_target, fast_mode, mod->selected_cells(), show_tempdir); else { assign_map.set(mod); @@ -1386,7 +1419,7 @@ struct AbcPass : public Pass { en_polarity = std::get<2>(it.first); en_sig = assign_map(std::get<3>(it.first)); abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, - !clk_sig.empty(), "$", keepff, delay_target, fast_mode, it.second); + !clk_sig.empty(), "$", keepff, delay_target, fast_mode, it.second, show_tempdir); assign_map.set(mod); } } diff --git a/passes/abc/blifparse.cc b/passes/abc/blifparse.cc index 38151985b..db87eec4a 100644 --- a/passes/abc/blifparse.cc +++ b/passes/abc/blifparse.cc @@ -129,7 +129,8 @@ RTLIL::Design *abc_parse_blif(FILE *f, std::string dff_name) if (p == NULL) goto error; - RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(p)); + IdString celltype = RTLIL::escape_id(p); + RTLIL::Cell *cell = module->addCell(NEW_ID, celltype); while ((p = strtok(NULL, " \t\r\n")) != NULL) { char *q = strchr(p, '='); From 29a555ec7eaa0e561f76c65258a50c54b6468546 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 17:10:37 +0100 Subject: [PATCH 216/492] Added statehash to ezSAT --- libs/ezsat/ezsat.cc | 49 +++++++++++++++++++++++++++++++++++++++------ libs/ezsat/ezsat.h | 3 +++ passes/opt/share.cc | 8 ++++++-- 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/libs/ezsat/ezsat.cc b/libs/ezsat/ezsat.cc index b713c4c91..1224fd3a9 100644 --- a/libs/ezsat/ezsat.cc +++ b/libs/ezsat/ezsat.cc @@ -42,6 +42,8 @@ static std::string my_int_to_string(int i) ezSAT::ezSAT() { + statehash = 5381; + flag_keep_cnf = false; flag_non_incremental = false; @@ -65,6 +67,11 @@ ezSAT::~ezSAT() { } +void ezSAT::addhash(unsigned int h) +{ + statehash = ((statehash << 5) + statehash) ^ h; +} + int ezSAT::value(bool val) { return val ? CONST_TRUE : CONST_FALSE; @@ -113,8 +120,14 @@ int ezSAT::expression(OpId op, const std::vector &args) myArgs.reserve(args.size()); bool xorRemovedOddTrues = false; + addhash(__LINE__); + addhash(op); + for (auto arg : args) { + addhash(__LINE__); + addhash(arg); + if (arg == 0) continue; if (op == OpAnd && arg == CONST_TRUE) @@ -200,7 +213,13 @@ int ezSAT::expression(OpId op, const std::vector &args) expressions.push_back(myExpr); } - return xorRemovedOddTrues ? NOT(id) : id; + if (xorRemovedOddTrues) + id = NOT(id); + + addhash(__LINE__); + addhash(id); + + return id; } void ezSAT::lookup_literal(int id, std::string &name) const @@ -387,6 +406,9 @@ bool ezSAT::eliminated(int) void ezSAT::assume(int id) { + addhash(__LINE__); + addhash(id); + if (id < 0) { assert(0 < -id && -id <= int(expressions.size())); @@ -429,6 +451,10 @@ void ezSAT::assume(int id) void ezSAT::add_clause(const std::vector &args) { + addhash(__LINE__); + for (auto arg : args) + addhash(arg); + cnfClauses.push_back(args); cnfClausesCount++; } @@ -519,6 +545,10 @@ std::string ezSAT::cnfLiteralInfo(int idx) const int ezSAT::bind(int id, bool auto_freeze) { + addhash(__LINE__); + addhash(id); + addhash(auto_freeze); + if (id >= 0) { assert(0 < id && id <= int(literals.size())); cnfLiteralVariables.resize(literals.size()); @@ -561,10 +591,13 @@ int ezSAT::bind(int id, bool auto_freeze) while (args.size() > 1) { std::vector newArgs; for (int i = 0; i < int(args.size()); i += 2) - if (i+1 == int(args.size())) + if (i+1 == int(args.size())) { newArgs.push_back(args[i]); - else - newArgs.push_back(OR(AND(args[i], NOT(args[i+1])), AND(NOT(args[i]), args[i+1]))); + } else { + int sub1 = AND(args[i], NOT(args[i+1])); + int sub2 = AND(NOT(args[i]), args[i+1]); + newArgs.push_back(OR(sub1, sub2)); + } args.swap(newArgs); } idx = bind(args.at(0), false); @@ -575,12 +608,16 @@ int ezSAT::bind(int id, bool auto_freeze) std::vector invArgs; for (auto arg : args) invArgs.push_back(NOT(arg)); - idx = bind(OR(expression(OpAnd, args), expression(OpAnd, invArgs)), false); + int sub1 = expression(OpAnd, args); + int sub2 = expression(OpAnd, invArgs); + idx = bind(OR(sub1, sub2), false); goto assign_idx; } if (op == OpITE) { - idx = bind(OR(AND(args[0], args[1]), AND(NOT(args[0]), args[2])), false); + int sub1 = AND(args[0], args[1]); + int sub2 = AND(NOT(args[0]), args[2]); + idx = bind(OR(sub1, sub2), false); goto assign_idx; } diff --git a/libs/ezsat/ezsat.h b/libs/ezsat/ezsat.h index 5c8c1ed0c..a20713bc1 100644 --- a/libs/ezsat/ezsat.h +++ b/libs/ezsat/ezsat.h @@ -83,6 +83,9 @@ public: ezSAT(); virtual ~ezSAT(); + unsigned int statehash; + void addhash(unsigned int); + void keep_cnf() { flag_keep_cnf = true; } void non_incremental() { flag_non_incremental = true; } diff --git a/passes/opt/share.cc b/passes/opt/share.cc index e2c31bec5..7ab50991d 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -1226,7 +1226,9 @@ struct ShareWorker for (auto it : exclusive_ctrls) if (satgen.importedSigBit(it.first) && satgen.importedSigBit(it.second)) { log(" Adding exclusive control bits: %s vs. %s\n", log_signal(it.first), log_signal(it.second)); - ez.assume(ez.NOT(ez.AND(satgen.importSigBit(it.first), satgen.importSigBit(it.second)))); + int sub1 = satgen.importSigBit(it.first); + int sub2 = satgen.importSigBit(it.second); + ez.assume(ez.NOT(ez.AND(sub1, sub2))); } if (!ez.solve(ez.expression(ez.OpOr, cell_active))) { @@ -1248,7 +1250,9 @@ struct ShareWorker std::vector sat_model = satgen.importSigSpec(all_ctrl_signals); std::vector sat_model_values; - ez.assume(ez.AND(ez.expression(ez.OpOr, cell_active), ez.expression(ez.OpOr, other_cell_active))); + int sub1 = ez.expression(ez.OpOr, cell_active); + int sub2 = ez.expression(ez.OpOr, other_cell_active); + ez.assume(ez.AND(sub1, sub2)); log(" Size of SAT problem: %d cells, %d variables, %d clauses\n", GetSize(sat_cells), ez.numCnfVariables(), ez.numCnfClauses()); From ed8f1b42fcf8db801e35da5c242d13560b458580 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 20:23:22 +0100 Subject: [PATCH 217/492] Fixed memory corruption in "splice" command --- passes/cmds/splice.cc | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc index d3ef15ab4..3e0158c5c 100644 --- a/passes/cmds/splice.cc +++ b/passes/cmds/splice.cc @@ -182,11 +182,13 @@ struct SpliceWorker if (design->selected(module, it.second)) selected_bits.add(sigmap(it.second)); - for (auto &it : module->cells_) { - if (!sel_by_wire && !design->selected(module, it.second)) + std::vector mod_cells = module->cells(); + + for (auto cell : mod_cells) { + if (!sel_by_wire && !design->selected(module, cell)) continue; - for (auto &conn : it.second->connections_) - if (ct.cell_input(it.second->type, conn.first)) { + for (auto &conn : cell->connections_) + if (ct.cell_input(cell->type, conn.first)) { if (ports.size() > 0 && !ports.count(conn.first)) continue; if (no_ports.size() > 0 && no_ports.count(conn.first)) @@ -205,24 +207,25 @@ struct SpliceWorker } std::vector> rework_wires; + std::vector mod_wires = module->wires(); - for (auto &it : module->wires_) - if (!no_outputs && it.second->port_output) { - if (!design->selected(module, it.second)) + for (auto mod : mod_wires) + if (!no_outputs && mod->port_output) { + if (!design->selected(module, mod)) continue; - RTLIL::SigSpec sig = sigmap(it.second); + RTLIL::SigSpec sig = sigmap(mod); if (driven_chunks.count(sig) > 0) continue; RTLIL::SigSpec new_sig = get_spliced_signal(sig); if (new_sig != sig) - rework_wires.push_back(std::pair(it.second, new_sig)); + rework_wires.push_back(std::pair(mod, new_sig)); } else - if (!it.second->port_input) { - RTLIL::SigSpec sig = sigmap(it.second); + if (!mod->port_input) { + RTLIL::SigSpec sig = sigmap(mod); if (spliced_signals_cache.count(sig) && spliced_signals_cache.at(sig) != sig) - rework_wires.push_back(std::pair(it.second, spliced_signals_cache.at(sig))); + rework_wires.push_back(std::pair(mod, spliced_signals_cache.at(sig))); else if (sliced_signals_cache.count(sig) && sliced_signals_cache.at(sig) != sig) - rework_wires.push_back(std::pair(it.second, sliced_signals_cache.at(sig))); + rework_wires.push_back(std::pair(mod, sliced_signals_cache.at(sig))); } for (auto &it : rework_wires) From 2f1e6aa2564bdc5d9f1a5fd8e879322739e0ffa3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 20:24:28 +0100 Subject: [PATCH 218/492] Improved free list management in hashlib --- kernel/hashlib.h | 120 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 108 insertions(+), 12 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 4e8c00026..5f977c5f1 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -175,6 +175,7 @@ class dict std::vector hashtable; std::vector entries; int free_list, counter, begin_n; + int begin_seek_count; OPS ops; void init() @@ -182,6 +183,7 @@ class dict free_list = -1; counter = 0; begin_n = -1; + begin_seek_count = 0; } void init_from(const dict &other) @@ -209,6 +211,43 @@ class dict return hash; } + void upd_begin_n() + { + if (begin_n < -1) { + begin_n = -(begin_n+2); + if (begin_n > int(entries.size())) + begin_n = int(entries.size()); + do { + if (begin_seek_count++ > int(entries.size())) + refree(); + else + begin_n--; + } while (begin_n >= 0 && entries[begin_n].is_free()); + } + } + + void refree() + { + free_list = -1; + begin_n = -1; + + int last_free = -1; + for (int i = 0; i < int(entries.size()); i++) + if (entries[i].is_free()) { + if (last_free != -1) + entries[last_free].set_next_free(i); + else + free_list = i; + last_free = i; + } else + begin_n = i; + + if (last_free != -1) + entries[last_free].set_next_free(-1); + + begin_seek_count = 0; + } + void rehash() { free_list = -1; @@ -217,16 +256,25 @@ class dict for (auto &h : hashtable) h = -1; + int last_free = -1; for (int i = 0; i < int(entries.size()); i++) if (entries[i].is_free()) { - entries[i].set_next_free(free_list); - free_list = i; + if (last_free != -1) + entries[last_free].set_next_free(i); + else + free_list = i; + last_free = i; } else { int hash = mkhash(entries[i].udata.first); entries[i].set_next_used(hashtable[hash]); hashtable[hash] = i; begin_n = i; } + + if (last_free != -1) + entries[last_free].set_next_free(-1); + + begin_seek_count = 0; } int do_erase(const K &key, int hash) @@ -247,7 +295,7 @@ class dict if (--counter == 0) clear(); else if (index == begin_n) - do begin_n--; while (begin_n >= 0 && entries[begin_n].is_free()); + begin_n = -(begin_n+2); return 1; } last_index = index; @@ -287,7 +335,7 @@ class dict entries[i].udata = value; entries[i].set_next_used(hashtable[hash]); hashtable[hash] = i; - if (begin_n < i) + if ((begin_n < -1 && -(begin_n+2) <= i) || (begin_n >= -1 && begin_n <= i)) begin_n = i; counter++; return i; @@ -486,10 +534,10 @@ public: bool empty() const { return counter == 0; } void clear() { hashtable.clear(); entries.clear(); init(); } - iterator begin() { return iterator(this, begin_n); } + iterator begin() { upd_begin_n(); return iterator(this, begin_n); } iterator end() { return iterator(this, -1); } - const_iterator begin() const { return const_iterator(this, begin_n); } + const_iterator begin() const { ((dict*)this)->upd_begin_n(); return const_iterator(this, begin_n); } const_iterator end() const { return const_iterator(this, -1); } }; @@ -514,6 +562,7 @@ class pool std::vector hashtable; std::vector entries; int free_list, counter, begin_n; + int begin_seek_count; OPS ops; void init() @@ -521,6 +570,7 @@ class pool free_list = -1; counter = 0; begin_n = -1; + begin_seek_count = 0; } void init_from(const pool &other) @@ -548,6 +598,43 @@ class pool return hash; } + void upd_begin_n() + { + if (begin_n < -1) { + begin_n = -(begin_n+2); + if (begin_n > int(entries.size())) + begin_n = int(entries.size()); + do { + if (begin_seek_count++ > int(entries.size())) + refree(); + else + begin_n--; + } while (begin_n >= 0 && entries[begin_n].is_free()); + } + } + + void refree() + { + free_list = -1; + begin_n = -1; + + int last_free = -1; + for (int i = 0; i < int(entries.size()); i++) + if (entries[i].is_free()) { + if (last_free != -1) + entries[last_free].set_next_free(i); + else + free_list = i; + last_free = i; + } else + begin_n = i; + + if (last_free != -1) + entries[last_free].set_next_free(-1); + + begin_seek_count = 0; + } + void rehash() { free_list = -1; @@ -556,16 +643,25 @@ class pool for (auto &h : hashtable) h = -1; + int last_free = -1; for (int i = 0; i < int(entries.size()); i++) if (entries[i].is_free()) { - entries[i].set_next_free(free_list); - free_list = i; + if (last_free != -1) + entries[last_free].set_next_free(i); + else + free_list = i; + last_free = i; } else { int hash = mkhash(entries[i].key); entries[i].set_next_used(hashtable[hash]); hashtable[hash] = i; begin_n = i; } + + if (last_free != -1) + entries[last_free].set_next_free(-1); + + begin_seek_count = 0; } int do_erase(const K &key, int hash) @@ -586,7 +682,7 @@ class pool if (--counter == 0) clear(); else if (index == begin_n) - do begin_n--; while (begin_n >= 0 && entries[begin_n].is_free()); + begin_n = -(begin_n+2); return 1; } last_index = index; @@ -626,7 +722,7 @@ class pool entries[i].key = key; entries[i].set_next_used(hashtable[hash]); hashtable[hash] = i; - if (begin_n < i) + if ((begin_n < -1 && -(begin_n+2) <= i) || (begin_n >= -1 && begin_n <= i)) begin_n = i; counter++; return i; @@ -805,10 +901,10 @@ public: bool empty() const { return counter == 0; } void clear() { hashtable.clear(); entries.clear(); init(); } - iterator begin() { return iterator(this, begin_n); } + iterator begin() { upd_begin_n(); return iterator(this, begin_n); } iterator end() { return iterator(this, -1); } - const_iterator begin() const { return const_iterator(this, begin_n); } + const_iterator begin() const { ((pool*)this)->upd_begin_n(); return const_iterator(this, begin_n); } const_iterator end() const { return const_iterator(this, -1); } }; From d72a66644035d43f81afa78283ecf15c520909ec Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Dec 2014 21:26:15 +0100 Subject: [PATCH 219/492] Put dummy reference to empty idstring in yosys_shutdown() --- kernel/yosys.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index fa9fffa62..ac1bc7abf 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -420,6 +420,9 @@ void yosys_shutdown() loaded_plugins.clear(); loaded_plugin_aliases.clear(); #endif + + IdString empty_id; + IdString::put_reference(empty_id.index_); } RTLIL::IdString new_id(std::string file, int line, std::string func) From c64b1de11da8db9e912e0a293d5c9c8a9bc31096 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Dec 2014 11:41:24 +0100 Subject: [PATCH 220/492] Fixed build with SMALL=1 --- passes/opt/Makefile.inc | 3 +++ passes/techmap/Makefile.inc | 2 +- techlibs/common/Makefile.inc | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index 3a8d27f93..6b075cd9a 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -6,6 +6,9 @@ OBJS += passes/opt/opt_reduce.o OBJS += passes/opt/opt_rmdff.o OBJS += passes/opt/opt_clean.o OBJS += passes/opt/opt_const.o + +ifneq ($(SMALL),1) OBJS += passes/opt/share.o OBJS += passes/opt/wreduce.o +endif diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 773a099ac..d8a433164 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -2,13 +2,13 @@ OBJS += passes/techmap/techmap.o OBJS += passes/techmap/simplemap.o OBJS += passes/techmap/dfflibmap.o +OBJS += passes/techmap/maccmap.o OBJS += passes/techmap/libparse.o ifneq ($(SMALL),1) OBJS += passes/techmap/iopadmap.o OBJS += passes/techmap/hilomap.o OBJS += passes/techmap/extract.o -OBJS += passes/techmap/maccmap.o OBJS += passes/techmap/alumacc.o OBJS += passes/techmap/dff2dffe.o endif diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index 7c8cc2f66..0607ca1a1 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -1,5 +1,7 @@ +ifneq ($(SMALL),1) OBJS += techlibs/common/synth.o +endif EXTRA_TARGETS += techlibs/common/blackbox.v From 3857e1cb66e294774745534ce6cc01b5c495b333 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Dec 2014 13:22:33 +0100 Subject: [PATCH 221/492] Improvements in hashlib --- kernel/hashlib.h | 155 ++++++++++++++++++++++------------------------- 1 file changed, 72 insertions(+), 83 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 5f977c5f1..b02abfadd 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -17,7 +17,8 @@ namespace hashlib { -const int config_size_factor = 3; +const int hashtable_size_trigger = 2; +const int hashtable_size_factor = 3; // The XOR version of DJB2 // (traditionally 5381 is used as starting value for the djb2 hash) @@ -121,37 +122,29 @@ struct hash_obj_ops { } }; -inline int hashtable_size(int old_size) +inline int hashtable_size(int min_size) { - // prime numbers, approx. in powers of two - if (old_size < 53) return 53; - if (old_size < 113) return 113; - if (old_size < 251) return 251; - if (old_size < 503) return 503; - if (old_size < 1129) return 1129; - if (old_size < 2503) return 2503; - if (old_size < 5023) return 5023; - if (old_size < 11299) return 11299; - if (old_size < 25097) return 25097; - if (old_size < 50291) return 50291; - if (old_size < 112997) return 112997; - if (old_size < 251003) return 251003; - if (old_size < 503003) return 503003; - if (old_size < 1129991) return 1129991; - if (old_size < 2509993) return 2509993; - if (old_size < 5029991) return 5029991; - if (old_size < 11299997) return 11299997; - if (old_size < 25099999) return 25099999; - if (old_size < 50299999) return 50299999; - if (old_size < 113000009) return 113000009; - if (old_size < 250999999) return 250999999; - if (old_size < 503000009) return 503000009; - if (old_size < 1129999999) return 1129999999; + static std::vector primes = { + 23, 29, 37, 47, 59, 79, 101, 127, 163, 211, 269, 337, 431, 541, 677, + 853, 1069, 1361, 1709, 2137, 2677, 3347, 4201, 5261, 6577, 8231, 10289, + 12889, 16127, 20161, 25219, 31531, 39419, 49277, 61603, 77017, 96281, + 120371, 150473, 188107, 235159, 293957, 367453, 459317, 574157, 717697, + 897133, 1121423, 1401791, 1752239, 2190299, 2737937, 3422429, 4278037, + 5347553, 6684443, 8355563, 10444457, 13055587, 16319519, 20399411, + 25499291, 31874149, 39842687, 49803361, 62254207, 77817767, 97272239, + 121590311, 151987889, 189984863, 237481091, 296851369, 371064217 + }; - if (sizeof(old_size) == 4) - throw std::length_error("hash table exceeded maximum size. recompile with -mint64."); + for (auto p : primes) + if (p > min_size) return p; - return old_size * 2; + if (sizeof(int) == 4) + throw std::length_error("hash table exceeded maximum size. use a ILP64 abi for larger tables."); + + for (auto p : primes) + if (100129 * p > min_size) return 100129 * p; + + throw std::length_error("hash table exceeded maximum size."); } template> @@ -192,14 +185,12 @@ class dict entries.clear(); counter = other.size(); - int new_size = hashtable_size(config_size_factor * counter); - hashtable.resize(new_size); - new_size = new_size / config_size_factor + 1; - entries.reserve(new_size); + begin_n = counter - 1; + entries.reserve(counter); for (auto &it : other) entries.push_back(entry_t(it)); - entries.resize(new_size); + rehash(); } @@ -211,18 +202,12 @@ class dict return hash; } - void upd_begin_n() + void upd_begin_n(bool do_refree = true) { if (begin_n < -1) { begin_n = -(begin_n+2); - if (begin_n > int(entries.size())) - begin_n = int(entries.size()); - do { - if (begin_seek_count++ > int(entries.size())) - refree(); - else - begin_n--; - } while (begin_n >= 0 && entries[begin_n].is_free()); + while (begin_n >= 0 && entries[begin_n].is_free()) { begin_seek_count++; begin_n--; } + if (do_refree && begin_seek_count > int(entries.size() / 2)) refree(); } } @@ -250,11 +235,14 @@ class dict void rehash() { + upd_begin_n(false); + entries.resize(begin_n + 1); + free_list = -1; begin_n = -1; - for (auto &h : hashtable) - h = -1; + hashtable.clear(); + hashtable.resize(hashtable_size(entries.size() * hashtable_size_factor), -1); int last_free = -1; for (int i = 0; i < int(entries.size()); i++) @@ -319,15 +307,18 @@ class dict { if (free_list < 0) { - int i = entries.size(); - int new_size = hashtable_size(config_size_factor * entries.size()); - hashtable.resize(new_size); - entries.resize(new_size / config_size_factor + 1); - entries[i].udata = value; - entries[i].set_next_used(0); - counter++; - rehash(); - return i; + free_list = entries.size(); + entries.push_back(entry_t()); + + if (entries.size() * hashtable_size_trigger > hashtable.size()) { + int i = free_list; + entries[i].udata = value; + entries[i].set_next_used(0); + begin_n = i; + counter++; + rehash(); + return i; + } } int i = free_list; @@ -384,8 +375,7 @@ public: dict(dict &&other) { - free_list = -1; - counter = 0; + init(); swap(other); } @@ -504,6 +494,7 @@ public: std::swap(free_list, other.free_list); std::swap(counter, other.counter); std::swap(begin_n, other.begin_n); + std::swap(begin_seek_count, other.begin_seek_count); } bool operator==(const dict &other) const { @@ -579,14 +570,12 @@ class pool entries.clear(); counter = other.size(); - int new_size = hashtable_size(config_size_factor * counter); - hashtable.resize(new_size); - new_size = new_size / config_size_factor + 1; - entries.reserve(new_size); + begin_n = counter - 1; + entries.reserve(counter); for (auto &it : other) entries.push_back(entry_t(it)); - entries.resize(new_size); + rehash(); } @@ -598,18 +587,12 @@ class pool return hash; } - void upd_begin_n() + void upd_begin_n(bool do_refree = true) { if (begin_n < -1) { begin_n = -(begin_n+2); - if (begin_n > int(entries.size())) - begin_n = int(entries.size()); - do { - if (begin_seek_count++ > int(entries.size())) - refree(); - else - begin_n--; - } while (begin_n >= 0 && entries[begin_n].is_free()); + while (begin_n >= 0 && entries[begin_n].is_free()) { begin_seek_count++; begin_n--; } + if (do_refree && begin_seek_count > int(entries.size() / 2)) refree(); } } @@ -637,11 +620,14 @@ class pool void rehash() { + upd_begin_n(false); + entries.resize(begin_n + 1); + free_list = -1; begin_n = -1; - for (auto &h : hashtable) - h = -1; + hashtable.clear(); + hashtable.resize(hashtable_size(entries.size() * hashtable_size_factor), -1); int last_free = -1; for (int i = 0; i < int(entries.size()); i++) @@ -706,15 +692,18 @@ class pool { if (free_list < 0) { - int i = entries.size(); - int new_size = hashtable_size(config_size_factor * entries.size()); - hashtable.resize(new_size); - entries.resize(new_size / config_size_factor + 1); - entries[i].key = key; - entries[i].set_next_used(0); - counter++; - rehash(); - return i; + free_list = entries.size(); + entries.push_back(entry_t()); + + if (entries.size() * hashtable_size_trigger > hashtable.size()) { + int i = free_list; + entries[i].key = key; + entries[i].set_next_used(0); + begin_n = i; + counter++; + rehash(); + return i; + } } int i = free_list; @@ -771,8 +760,7 @@ public: pool(pool &&other) { - free_list = -1; - counter = 0; + init(); swap(other); } @@ -871,6 +859,7 @@ public: std::swap(free_list, other.free_list); std::swap(counter, other.counter); std::swap(begin_n, other.begin_n); + std::swap(begin_seek_count, other.begin_seek_count); } bool operator==(const pool &other) const { From 120a8313d915c2ebac43c8bf0b8216b240e769c1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Dec 2014 13:30:22 +0100 Subject: [PATCH 222/492] Small optimization in hashlib --- kernel/hashlib.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index b02abfadd..c93e00a09 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -526,10 +526,10 @@ public: void clear() { hashtable.clear(); entries.clear(); init(); } iterator begin() { upd_begin_n(); return iterator(this, begin_n); } - iterator end() { return iterator(this, -1); } + iterator end() { return iterator(nullptr, -1); } const_iterator begin() const { ((dict*)this)->upd_begin_n(); return const_iterator(this, begin_n); } - const_iterator end() const { return const_iterator(this, -1); } + const_iterator end() const { return const_iterator(nullptr, -1); } }; template> @@ -891,10 +891,10 @@ public: void clear() { hashtable.clear(); entries.clear(); init(); } iterator begin() { upd_begin_n(); return iterator(this, begin_n); } - iterator end() { return iterator(this, -1); } + iterator end() { return iterator(nullptr, -1); } const_iterator begin() const { ((pool*)this)->upd_begin_n(); return const_iterator(this, begin_n); } - const_iterator end() const { return const_iterator(this, -1); } + const_iterator end() const { return const_iterator(nullptr, -1); } }; } /* namespace hashlib */ From ba43cf5807dadac970ff10afed4963d1ee329217 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Dec 2014 13:33:29 +0100 Subject: [PATCH 223/492] Fixed simlib entries for $memrd and $memwr --- techlibs/common/simlib.v | 2 ++ 1 file changed, 2 insertions(+) diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index e241cd3ce..bacf4a17e 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1449,6 +1449,7 @@ parameter WIDTH = 8; parameter CLK_ENABLE = 0; parameter CLK_POLARITY = 0; +parameter TRANSPARENT = 0; input CLK; input [ABITS-1:0] ADDR; @@ -1473,6 +1474,7 @@ parameter WIDTH = 8; parameter CLK_ENABLE = 0; parameter CLK_POLARITY = 0; +parameter PRIORITY = 0; input CLK; input [WIDTH-1:0] EN; From 06750987331a3d832ea83f2205c56612d3506332 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Dec 2014 18:51:24 +0100 Subject: [PATCH 224/492] added hashlib::mkhash_init --- kernel/hashlib.h | 8 +++++--- kernel/rtlil.cc | 2 +- kernel/rtlil.h | 2 +- kernel/yosys.h | 1 + 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index c93e00a09..0b6e94a32 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -21,13 +21,15 @@ const int hashtable_size_trigger = 2; const int hashtable_size_factor = 3; // The XOR version of DJB2 -// (traditionally 5381 is used as starting value for the djb2 hash) inline unsigned int mkhash(unsigned int a, unsigned int b) { return ((a << 5) + a) ^ b; } +// traditionally 5381 is used as starting value for the djb2 hash +const unsigned int mkhash_init = 5381; + // The ADD version of DJB2 -// (use this version for cache locality in b) +// (usunsigned int mkhashe this version for cache locality in b) inline unsigned int mkhash_add(unsigned int a, unsigned int b) { return ((a << 5) + a) + b; } @@ -96,7 +98,7 @@ struct hash_cstr_ops { return true; } unsigned int hash(const char *a) const { - unsigned int hash = 5381; + unsigned int hash = mkhash_init; while (*a) hash = mkhash(hash, *(a++)); return hash; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 912df7903..cd2232c8c 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2325,7 +2325,7 @@ void RTLIL::SigSpec::updhash() const cover("kernel.rtlil.sigspec.hash"); that->pack(); - that->hash_ = 5381; + that->hash_ = mkhash_init; for (auto &c : that->chunks_) if (c.wire == NULL) { for (auto &v : c.data) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index bb9e85d93..739b701f8 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -463,7 +463,7 @@ struct RTLIL::Const inline int size() const { return bits.size(); } inline unsigned int hash() const { - unsigned int h = 5381; + unsigned int h = mkhash_init; for (auto b : bits) mkhash(h, b); return h; diff --git a/kernel/yosys.h b/kernel/yosys.h index a4836f35a..5f3c3577d 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -138,6 +138,7 @@ YOSYS_NAMESPACE_BEGIN using std::vector; using std::string; using hashlib::mkhash; +using hashlib::mkhash_init; using hashlib::mkhash_add; using hashlib::mkhash_xorshift; using hashlib::hash_ops; From 4606addfefc3edcc625e27cbbf9b11cc9d93594f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Dec 2014 19:38:40 +0100 Subject: [PATCH 225/492] Fixed typo in ABC command --- passes/abc/abc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 9ee8aa1b0..78d8fc434 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -29,8 +29,8 @@ // Kahn, Arthur B. (1962), "Topological sorting of large networks", Communications of the ACM 5 (11): 558–562, doi:10.1145/368996.369025 // http://en.wikipedia.org/wiki/Topological_sorting -#define ABC_COMMAND_LIB "strash; scorr; ifraig; retime {D}; strash; dchf; map {D}" -#define ABC_COMMAND_CTR "strash; scorr; ifraig; retime {D}; strash; dchf; map {D}; buffer; upsize {D}; dnsize {D}; stime -p" +#define ABC_COMMAND_LIB "strash; scorr; ifraig; retime {D}; strash; dch -f; map {D}" +#define ABC_COMMAND_CTR "strash; scorr; ifraig; retime {D}; strash; dch -f; map {D}; buffer; upsize {D}; dnsize {D}; stime -p" #define ABC_COMMAND_LUT "strash; scorr; ifraig; retime; strash; dch -f; if" #define ABC_COMMAND_DFL "strash; scorr; ifraig; retime; strash; dch -f; map" From eceecfeb8cf13f9afc200ab7eb7e93ff8f2acac4 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Dec 2014 19:39:17 +0100 Subject: [PATCH 226/492] Added more information to CodingReadme --- CodingReadme | 116 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 110 insertions(+), 6 deletions(-) diff --git a/CodingReadme b/CodingReadme index 03de3fc17..bdadf821d 100644 --- a/CodingReadme +++ b/CodingReadme @@ -4,19 +4,123 @@ Getting Started =============== -Reading List ------------- +Outline of a Yosys command +-------------------------- -To write Yosys C++ code you need to know at least the following classes in kernel/rtlil.h: +Here is a the C++ code for a "hello_world" Yosys command (hello.cc): + + #include "kernel/yosys.h" + + USING_YOSYS_NAMESPACE + PRIVATE_NAMESPACE_BEGIN + + struct HelloWorldPass : public Pass { + HelloWorldPass() : Pass("hello_world") { } + virtual void execute(vector, Design*) { + log("Hello World!\n"); + } + } HelloWorldPass; + + PRIVATE_NAMESPACE_END + +This can be built into a Yosys module using the following command: + + yosys-config --exec --cxx --cxxflags --ldflags -o hello.so -shared hello.cc --ldlibs + +And then executed using the following command: + + yosys -m hello.so -p hello_world + + +Yosys Data Structures +--------------------- + +Here is a short list of data structures that you should make yourself familiar +with before you write C++ code for Yosys. The following data structures are all +defined when "kernel/yosys.h" is included and USING_YOSYS_NAMESPACE is used. + + 1. Yosys Container Classes + +Yosys uses dict and pool as main container classes. dict is +essentially a replacement for std::unordered_map and pool is +essentially a replacement for std::unordered_set. The main differences are: + + - dict and pool are about 2x faster than the std containers + + - references to elements in a dict or pool are invalidated by + insert operations (just like you are used from std::vector). + + - dict and pool will have the same order of iteration across + all compilers and architectures. + + 2. Standard STL data types + +In Yosys we use std::vector and std::string whenever applicable. When +dict and pool are not suitable then std::map and std::set +are used instead. + +The types std::vector and std::string are also available as vector +and string in the Yosys namespace. + + 3. RTLIL objects + +The current design (essentially a collection of modules, each defined by a +netlist) is stored in memory using RTLIL object (declared in kernel/rtlil.h, +automatically included by kernel/yosys.h). You should glance over at least +the declarations for the following types in kernel/rtlil.h: + + RTLIL::IdString + This is a handle for an identifier (e.g. cell or wire name). + It feels a lot like a std::string, but is only a single int + in size. (The actual string is stored in a global lookup + table.) + + RTLIL::SigBit + A single signal bit. I.e. either a constant (0, 1, x, z) or + a single bit from a wire. + + RTLIL::SigSpec + Essentially a vector of SigBits. RTLIL::Wire RTLIL::Cell + The building blocks of the netlist in a module. + RTLIL::Module - RTLIL::SigSpec + RTLIL::Design + The module is a container with connected cells and wires + in it. The design is a container with modules in it. + +All this types are also available without the RTLIL:: prefix in the Yosys +namespace. + + 4. SigMap and other Helper Classes + +There are a couple of additional helper classes that are in wide use +in Yosys. Most importantly there is SigMap (declared in kernel.sigtools.h). + +When a design has many wires in it that are connected to each other, then +a single signal bit can have multiple valid names. The SigMap object can +be used to map SigSpecs or SigBits to unique SigSpecs and SigBits that +consitently only uses one wire from a group of connected wires. For example: + + SigBit a = module->addWire(NEW_ID); + SigBit b = module->addWire(NEW_ID); + module->connect(a, b); + + log("%d\n", a == b); // will print 0 + + SigMap sigmap(module); + log("%d\n", sigmap(a) == sigmap(b)); // will print 1 + + +Example Code +------------ The following yosys commands are a good starting point if you are looking for examples of how to use the Yosys API: + manual/CHAPTER_Prog/stubnets.cc passes/opt/wreduce.cc passes/techmap/maccmap.cc @@ -25,7 +129,7 @@ Notes on the existing codebase ------------------------------ For historical reasons not all parts of Yosys adhere to the current coding -styles. When adding code to existing parts of the system, adhere to this guide +style. When adding code to existing parts of the system, adhere to this guide for the new code instead of trying to mimic the style of the surrounding code. @@ -62,7 +166,7 @@ gcc 4.6 is allowed in Yosys code. This will change in future releases. In general Yosys uses "int" instead of "size_t". To avoid compiler warnings for implicit type casts, always use "GetSize(foobar)" instead -of "foobar.size()". (GetSize() is defined by kernel/yosys.h) +of "foobar.size()". (GetSize() is defined in kernel/yosys.h) Use range-based for loops whenever applicable. From 972faab1c88186248d81e284e5767811bf5096e9 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Dec 2014 20:15:18 +0100 Subject: [PATCH 227/492] Fixed a bug in "select %ci %co %x" --- passes/cmds/select.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 91368f572..170061577 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -376,6 +376,7 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v RTLIL::Module *mod = mod_it.second; std::set selected_wires; + auto selected_members = lhs.selected_members[mod->name]; for (auto &it : mod->wires_) if (lhs.selected_member(mod_it.first, it.first) && limits.count(it.first) == 0) @@ -389,9 +390,9 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v for (size_t i = 0; i < conn_lhs.size(); i++) { if (conn_lhs[i].wire == NULL || conn_rhs[i].wire == NULL) continue; - if (mode != 'i' && selected_wires.count(conn_rhs[i].wire) && lhs.selected_members[mod->name].count(conn_lhs[i].wire->name) == 0) + if (mode != 'i' && selected_wires.count(conn_rhs[i].wire) && selected_members.count(conn_lhs[i].wire->name) == 0) lhs.selected_members[mod->name].insert(conn_lhs[i].wire->name), sel_objects++, max_objects--; - if (mode != 'o' && selected_wires.count(conn_lhs[i].wire) && lhs.selected_members[mod->name].count(conn_rhs[i].wire->name) == 0) + if (mode != 'o' && selected_wires.count(conn_lhs[i].wire) && selected_members.count(conn_rhs[i].wire->name) == 0) lhs.selected_members[mod->name].insert(conn_rhs[i].wire->name), sel_objects++, max_objects--; } } @@ -418,10 +419,10 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v is_output = mode == 'x' || ct.cell_output(cell.second->type, conn.first); for (auto &chunk : conn.second.chunks()) if (chunk.wire != NULL) { - if (max_objects != 0 && selected_wires.count(chunk.wire) > 0 && lhs.selected_members[mod->name].count(cell.first) == 0) + if (max_objects != 0 && selected_wires.count(chunk.wire) > 0 && selected_members.count(cell.first) == 0) if (mode == 'x' || (mode == 'i' && is_output) || (mode == 'o' && is_input)) lhs.selected_members[mod->name].insert(cell.first), sel_objects++, max_objects--; - if (max_objects != 0 && lhs.selected_members[mod->name].count(cell.first) > 0 && limits.count(cell.first) == 0 && lhs.selected_members[mod->name].count(chunk.wire->name) == 0) + if (max_objects != 0 && selected_members.count(cell.first) > 0 && limits.count(cell.first) == 0 && selected_members.count(chunk.wire->name) == 0) if (mode == 'x' || (mode == 'i' && is_input) || (mode == 'o' && is_output)) lhs.selected_members[mod->name].insert(chunk.wire->name), sel_objects++, max_objects--; } From 50fff2b24061208a4b7c0ff9a4839e1938c66140 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Dec 2014 22:31:04 +0100 Subject: [PATCH 228/492] print timing details (-d) in -q mode --- kernel/driver.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/driver.cc b/kernel/driver.cc index cdf784602..b7cb414ce 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -334,6 +334,10 @@ int main(int argc, char **argv) log_hasher = nullptr; log_spacer(); + + if (log_errfile != NULL && timing_details) + log_files.push_back(stderr); + #ifdef _WIN32 log("End of script. Logfile hash: %s\n", hash.c_str()); #else From 11c3b81c08e7227275744fe08a1a91295ec23781 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Dec 2014 22:35:38 +0100 Subject: [PATCH 229/492] typo fix for "opt -fast" --- passes/opt/opt.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/opt/opt.cc b/passes/opt/opt.cc index 83a30ad77..25419375e 100644 --- a/passes/opt/opt.cc +++ b/passes/opt/opt.cc @@ -145,7 +145,7 @@ struct OptPass : public Pass { } } - log_header(fast_mode ? "Finished fast OPT passes." : "Finished OPT passes. (There is nothing left to do.)\n"); + log_header(fast_mode ? "Finished fast OPT passes.\n" : "Finished OPT passes. (There is nothing left to do.)\n"); log_pop(); } } OptPass; From 1909edfa9c9236b2dc22d18946fd44ff266bce14 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Dec 2014 22:54:42 +0100 Subject: [PATCH 230/492] improved -v option --- kernel/driver.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index b7cb414ce..f1bf0657b 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -86,6 +86,8 @@ int main(int argc, char **argv) bool print_stats = true; bool call_abort = false; bool timing_details = false; + bool mode_v = false; + bool mode_q = false; #ifdef YOSYS_ENABLE_READLINE int history_offset = 0; @@ -113,7 +115,8 @@ int main(int argc, char **argv) printf(" use this option twice to also quiet warning messages\n"); printf("\n"); printf(" -v \n"); - printf(" print log headers up to level to the console. (implies -q)\n"); + printf(" print log headers up to level to the console. (this\n"); + printf(" implies -q for everything except the 'End of script.' message.)\n"); printf("\n"); printf(" -t\n"); printf(" annotate all log messages with a time stamp\n"); @@ -235,11 +238,13 @@ int main(int argc, char **argv) } break; case 'q': + mode_q = true; if (log_errfile == stderr) log_quiet_warnings = true; log_errfile = stderr; break; case 'v': + mode_v = true; log_errfile = stderr; log_verbose_level = atoi(optarg); break; @@ -333,9 +338,11 @@ int main(int argc, char **argv) delete log_hasher; log_hasher = nullptr; + log_time = false; + yosys_xtrace = 0; log_spacer(); - if (log_errfile != NULL && timing_details) + if (mode_v && !mode_q) log_files.push_back(stderr); #ifdef _WIN32 From 6fef4b82a2315830f99eeca3a4e80697a90a8447 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Dec 2014 23:45:43 +0100 Subject: [PATCH 231/492] using pool<> in bitpattern.h --- kernel/bitpattern.h | 26 +++++++++++++------------- kernel/hashlib.h | 16 +++++++++++++++- kernel/yosys.h | 4 ++++ 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/kernel/bitpattern.h b/kernel/bitpattern.h index 4d88c8e34..7416a488d 100644 --- a/kernel/bitpattern.h +++ b/kernel/bitpattern.h @@ -29,7 +29,7 @@ struct BitPatternPool { int width; typedef std::vector bits_t; - std::set pool; + pool database; BitPatternPool(RTLIL::SigSpec sig) { @@ -42,7 +42,7 @@ struct BitPatternPool else pattern[i] = RTLIL::State::Sa; } - pool.insert(pattern); + database.insert(pattern); } } @@ -53,7 +53,7 @@ struct BitPatternPool std::vector pattern(width); for (int i = 0; i < width; i++) pattern[i] = RTLIL::State::Sa; - pool.insert(pattern); + database.insert(pattern); } } @@ -79,7 +79,7 @@ struct BitPatternPool bool has_any(RTLIL::SigSpec sig) { bits_t bits = sig2bits(sig); - for (auto &it : pool) + for (auto &it : database) if (match(it, bits)) return true; return false; @@ -88,13 +88,13 @@ struct BitPatternPool bool has_all(RTLIL::SigSpec sig) { bits_t bits = sig2bits(sig); - for (auto &it : pool) + for (auto &it : database) if (match(it, bits)) { for (int i = 0; i < width; i++) if (bits[i] > RTLIL::State::S1 && it[i] <= RTLIL::State::S1) - goto next_pool_entry; + goto next_database_entry; return true; - next_pool_entry:; + next_database_entry:; } return false; } @@ -104,17 +104,17 @@ struct BitPatternPool bool status = false; bits_t bits = sig2bits(sig); std::vector pattern_list; - for (auto &it : pool) + for (auto &it : database) if (match(it, bits)) pattern_list.push_back(it); for (auto pattern : pattern_list) { - pool.erase(pattern); + database.erase(pattern); for (int i = 0; i < width; i++) { if (pattern[i] != RTLIL::State::Sa || bits[i] == RTLIL::State::Sa) continue; bits_t new_pattern = pattern; new_pattern[i] = bits[i] == RTLIL::State::S1 ? RTLIL::State::S0 : RTLIL::State::S1; - pool.insert(new_pattern); + database.insert(new_pattern); } status = true; } @@ -123,15 +123,15 @@ struct BitPatternPool bool take_all() { - if (pool.empty()) + if (database.empty()) return false; - pool.clear(); + database.clear(); return true; } bool empty() { - return pool.empty(); + return database.empty(); } }; diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 0b6e94a32..3164282f2 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -62,7 +62,8 @@ template<> struct hash_ops { bool cmp(T a, T b) const { return a == b; } - unsigned int hash(unsigned int a) const { + template + unsigned int hash(T a) const { return a; } }; @@ -90,6 +91,19 @@ template struct hash_ops> { } }; +template struct hash_ops> { + bool cmp(std::vector a, std::vector b) const { + return a == b; + } + unsigned int hash(std::vector a) const { + hash_ops t_ops; + unsigned int h = mkhash_init; + for (auto k : a) + h = mkhash(h, t_ops.hash(k)); + return h; + } +}; + struct hash_cstr_ops { bool cmp(const char *a, const char *b) const { for (int i = 0; a[i] || b[i]; i++) diff --git a/kernel/yosys.h b/kernel/yosys.h index 5f3c3577d..2c9ca0dd9 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -221,6 +221,10 @@ YOSYS_NAMESPACE_END YOSYS_NAMESPACE_BEGIN +namespace hashlib { + template<> struct hash_ops : hash_ops {}; +} + void yosys_setup(); void yosys_shutdown(); From 60f16e17afc81d8bbae722c13ef173329129494a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 31 Dec 2014 03:55:13 +0100 Subject: [PATCH 232/492] hotfix for ModInfo --- kernel/modtools.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/modtools.h b/kernel/modtools.h index 558cc08b8..113b0918d 100644 --- a/kernel/modtools.h +++ b/kernel/modtools.h @@ -70,7 +70,7 @@ struct ModIndex : public RTLIL::Monitor SigMap sigmap; RTLIL::Module *module; - dict database; + std::map database; bool auto_reload_module; void port_add(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &sig) From 7d6a7fe2ce8936c7af09ba7661e1159bc403483d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 31 Dec 2014 03:56:09 +0100 Subject: [PATCH 233/492] IdString optimization --- kernel/rtlil.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 739b701f8..c40af88aa 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -121,6 +121,12 @@ namespace RTLIL global_id_index_[global_id_storage_.at(idx)] = idx; global_refcount_storage_.at(idx)++; + // Avoid Create->Delete->Create pattern + static IdString last_created_id; + put_reference(last_created_id.index_); + last_created_id.index_ = idx; + get_reference(last_created_id.index_); + if (yosys_xtrace) { log("#X# New IdString '%s' with index %d.\n", p, idx); log_backtrace("-X- ", yosys_xtrace-1); From c4bd6cb9d38f445da8db6734411fd7b067c3f499 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 31 Dec 2014 03:58:29 +0100 Subject: [PATCH 234/492] major rewrite of hashlib::dict<> --- kernel/hashlib.h | 337 +++++++++++++++++++---------------------------- 1 file changed, 132 insertions(+), 205 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 3164282f2..a34d194f1 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -140,8 +140,8 @@ struct hash_obj_ops { inline int hashtable_size(int min_size) { - static std::vector primes = { - 23, 29, 37, 47, 59, 79, 101, 127, 163, 211, 269, 337, 431, 541, 677, + static std::vector zero_and_some_primes = { + 0, 23, 29, 37, 47, 59, 79, 101, 127, 163, 211, 269, 337, 431, 541, 677, 853, 1069, 1361, 1709, 2137, 2677, 3347, 4201, 5261, 6577, 8231, 10289, 12889, 16127, 20161, 25219, 31531, 39419, 49277, 61603, 77017, 96281, 120371, 150473, 188107, 235159, 293957, 367453, 459317, 574157, 717697, @@ -151,13 +151,13 @@ inline int hashtable_size(int min_size) 121590311, 151987889, 189984863, 237481091, 296851369, 371064217 }; - for (auto p : primes) - if (p > min_size) return p; + for (auto p : zero_and_some_primes) + if (p >= min_size) return p; if (sizeof(int) == 4) throw std::length_error("hash table exceeded maximum size. use a ILP64 abi for larger tables."); - for (auto p : primes) + for (auto p : zero_and_some_primes) if (100129 * p > min_size) return 100129 * p; throw std::length_error("hash table exceeded maximum size."); @@ -168,49 +168,26 @@ class dict { struct entry_t { - int link; std::pair udata; + int next; - entry_t() : link(-1) { } - entry_t(const std::pair &udata) : link(1), udata(udata) { } - - bool is_free() const { return link < 0; } - int get_next() const { return (link > 0 ? link : -link) - 2; } - bool get_last() const { return get_next() == -1; } - void set_next_used(int next) { link = next + 2; } - void set_next_free(int next) { link = -(next + 2); } + entry_t() { } + entry_t(const std::pair &udata, int next) : udata(udata), next(next) { } }; std::vector hashtable; std::vector entries; - int free_list, counter, begin_n; - int begin_seek_count; OPS ops; - void init() - { - free_list = -1; - counter = 0; - begin_n = -1; - begin_seek_count = 0; +#if 0 + static inline void do_assert(bool cond) { + if (!cond) throw std::runtime_error("dict<> assert failed."); } +#else + static inline void do_assert(bool) { } +#endif - void init_from(const dict &other) - { - hashtable.clear(); - entries.clear(); - - counter = other.size(); - begin_n = counter - 1; - entries.reserve(counter); - - for (auto &it : other) - entries.push_back(entry_t(it)); - - rehash(); - } - - int mkhash(const K &key) const + int do_hash(const K &key) const { unsigned int hash = 0; if (!hashtable.empty()) @@ -218,145 +195,108 @@ class dict return hash; } - void upd_begin_n(bool do_refree = true) + void do_rehash() { - if (begin_n < -1) { - begin_n = -(begin_n+2); - while (begin_n >= 0 && entries[begin_n].is_free()) { begin_seek_count++; begin_n--; } - if (do_refree && begin_seek_count > int(entries.size() / 2)) refree(); - } - } - - void refree() - { - free_list = -1; - begin_n = -1; - - int last_free = -1; - for (int i = 0; i < int(entries.size()); i++) - if (entries[i].is_free()) { - if (last_free != -1) - entries[last_free].set_next_free(i); - else - free_list = i; - last_free = i; - } else - begin_n = i; - - if (last_free != -1) - entries[last_free].set_next_free(-1); - - begin_seek_count = 0; - } - - void rehash() - { - upd_begin_n(false); - entries.resize(begin_n + 1); - - free_list = -1; - begin_n = -1; - hashtable.clear(); hashtable.resize(hashtable_size(entries.size() * hashtable_size_factor), -1); - int last_free = -1; - for (int i = 0; i < int(entries.size()); i++) - if (entries[i].is_free()) { - if (last_free != -1) - entries[last_free].set_next_free(i); - else - free_list = i; - last_free = i; - } else { - int hash = mkhash(entries[i].udata.first); - entries[i].set_next_used(hashtable[hash]); - hashtable[hash] = i; - begin_n = i; - } - - if (last_free != -1) - entries[last_free].set_next_free(-1); - - begin_seek_count = 0; - } - - int do_erase(const K &key, int hash) - { - int last_index = -1; - int index = hashtable.empty() ? -1 : hashtable[hash]; - while (1) { - if (index < 0) - return 0; - if (ops.cmp(entries[index].udata.first, key)) { - if (last_index < 0) - hashtable[hash] = entries[index].get_next(); - else - entries[last_index].set_next_used(entries[index].get_next()); - entries[index].udata = std::pair(); - entries[index].set_next_free(free_list); - free_list = index; - if (--counter == 0) - clear(); - else if (index == begin_n) - begin_n = -(begin_n+2); - return 1; - } - last_index = index; - index = entries[index].get_next(); + for (int i = 0; i < int(entries.size()); i++) { + do_assert(-1 <= entries[i].next && entries[i].next < int(entries.size())); + int hash = do_hash(entries[i].udata.first); + entries[i].next = hashtable[hash]; + hashtable[hash] = i; } } - int lookup_index(const K &key, int hash) const + int do_erase(int index, int hash) { - int index = hashtable.empty() ? -1 : hashtable[hash]; - while (1) { - if (index < 0) - return -1; - if (ops.cmp(entries[index].udata.first, key)) - return index; - index = entries[index].get_next(); - } - } + do_assert(index < int(entries.size())); + if (hashtable.empty() || index < 0) + return 0; - int insert_at(const std::pair &value, int hash) - { - if (free_list < 0) + int k = hashtable[hash]; + if (k == index) { + hashtable[hash] = entries[index].next; + } else { + while (entries[k].next != index) { + k = entries[k].next; + do_assert(0 <= k && k < int(entries.size())); + } + entries[k].next = entries[index].next; + } + + int back_idx = entries.size()-1; + + if (index != back_idx) { - free_list = entries.size(); - entries.push_back(entry_t()); + int back_hash = do_hash(entries[back_idx].udata.first); - if (entries.size() * hashtable_size_trigger > hashtable.size()) { - int i = free_list; - entries[i].udata = value; - entries[i].set_next_used(0); - begin_n = i; - counter++; - rehash(); - return i; + k = hashtable[back_hash]; + if (k == back_idx) { + hashtable[back_hash] = index; + } else { + while (entries[k].next != back_idx) { + k = entries[k].next; + do_assert(0 <= k && k < int(entries.size())); + } + entries[k].next = index; } + + entries[index] = std::move(entries[back_idx]); } - int i = free_list; - free_list = entries[i].get_next(); - entries[i].udata = value; - entries[i].set_next_used(hashtable[hash]); - hashtable[hash] = i; - if ((begin_n < -1 && -(begin_n+2) <= i) || (begin_n >= -1 && begin_n <= i)) - begin_n = i; - counter++; - return i; + entries.pop_back(); + + if (entries.empty()) + hashtable.clear(); + + return 1; + } + + int do_lookup(const K &key, int &hash) const + { + if (hashtable.empty()) + return -1; + + if (entries.size() * hashtable_size_trigger > hashtable.size()) { + ((dict*)this)->do_rehash(); + hash = do_hash(key); + } + + int index = hashtable[hash]; + + while (index >= 0 && !ops.cmp(entries[index].udata.first, key)) { + index = entries[index].next; + do_assert(-1 <= index && index < int(entries.size())); + } + + return index; + } + + int do_insert(const std::pair &value, int &hash) + { + if (hashtable.empty()) { + entries.push_back(entry_t(value, -1)); + do_rehash(); + hash = do_hash(value.first); + } else { + entries.push_back(entry_t(value, hashtable[hash])); + hashtable[hash] = entries.size() - 1; + } + return entries.size() - 1; } public: class iterator { + friend dict; + protected: dict *ptr; int index; public: iterator() { } iterator(dict *ptr, int index) : ptr(ptr), index(index) { } - iterator operator++() { do index--; while (index >= 0 && ptr->entries[index].is_free()); return *this; } + iterator operator++() { index--; return *this; } bool operator==(const iterator &other) const { return index == other.index; } bool operator!=(const iterator &other) const { return index != other.index; } std::pair &operator*() { return ptr->entries[index].udata; } @@ -367,12 +307,14 @@ public: class const_iterator { + friend dict; + protected: const dict *ptr; int index; public: const_iterator() { } const_iterator(const dict *ptr, int index) : ptr(ptr), index(index) { } - const_iterator operator++() { do index--; while (index >= 0 && ptr->entries[index].is_free()); return *this; } + const_iterator operator++() { index--; return *this; } bool operator==(const const_iterator &other) const { return index == other.index; } bool operator!=(const const_iterator &other) const { return index != other.index; } const std::pair &operator*() const { return ptr->entries[index].udata; } @@ -381,23 +323,22 @@ public: dict() { - init(); } dict(const dict &other) { - init_from(other); + entries = other.entries; + do_rehash(); } dict(dict &&other) { - init(); swap(other); } dict &operator=(const dict &other) { - if (this != &other) - init_from(other); + entries = other.entries; + do_rehash(); return *this; } @@ -409,7 +350,6 @@ public: dict(const std::initializer_list> &list) { - init(); for (auto &it : list) insert(it); } @@ -417,7 +357,6 @@ public: template dict(InputIterator first, InputIterator last) { - init(); insert(first, last); } @@ -430,38 +369,39 @@ public: std::pair insert(const std::pair &value) { - int hash = mkhash(value.first); - int i = lookup_index(value.first, hash); + int hash = do_hash(value.first); + int i = do_lookup(value.first, hash); if (i >= 0) return std::pair(iterator(this, i), false); - i = insert_at(value, hash); + i = do_insert(value, hash); return std::pair(iterator(this, i), true); } int erase(const K &key) { - int hash = mkhash(key); - return do_erase(key, hash); + int hash = do_hash(key); + int index = do_lookup(key, hash); + return do_erase(index, hash); } iterator erase(iterator it) { - int hash = mkhash(it->first); - do_erase(it->first, hash); + int hash = do_hash(it->first); + do_erase(it.index, hash); return ++it; } int count(const K &key) const { - int hash = mkhash(key); - int i = lookup_index(key, hash); + int hash = do_hash(key); + int i = do_lookup(key, hash); return i < 0 ? 0 : 1; } iterator find(const K &key) { - int hash = mkhash(key); - int i = lookup_index(key, hash); + int hash = do_hash(key); + int i = do_lookup(key, hash); if (i < 0) return end(); return iterator(this, i); @@ -469,8 +409,8 @@ public: const_iterator find(const K &key) const { - int hash = mkhash(key); - int i = lookup_index(key, hash); + int hash = do_hash(key); + int i = do_lookup(key, hash); if (i < 0) return end(); return const_iterator(this, i); @@ -478,8 +418,8 @@ public: T& at(const K &key) { - int hash = mkhash(key); - int i = lookup_index(key, hash); + int hash = do_hash(key); + int i = do_lookup(key, hash); if (i < 0) throw std::out_of_range("dict::at()"); return entries[i].udata.second; @@ -487,8 +427,8 @@ public: const T& at(const K &key) const { - int hash = mkhash(key); - int i = lookup_index(key, hash); + int hash = do_hash(key); + int i = do_lookup(key, hash); if (i < 0) throw std::out_of_range("dict::at()"); return entries[i].udata.second; @@ -496,10 +436,10 @@ public: T& operator[](const K &key) { - int hash = mkhash(key); - int i = lookup_index(key, hash); + int hash = do_hash(key); + int i = do_lookup(key, hash); if (i < 0) - i = insert_at(std::pair(key, T()), hash); + i = do_insert(std::pair(key, T()), hash); return entries[i].udata.second; } @@ -507,29 +447,16 @@ public: { hashtable.swap(other.hashtable); entries.swap(other.entries); - std::swap(free_list, other.free_list); - std::swap(counter, other.counter); - std::swap(begin_n, other.begin_n); - std::swap(begin_seek_count, other.begin_seek_count); } bool operator==(const dict &other) const { - if (counter != other.counter) + if (size() != other.size()) return false; - if (counter == 0) - return true; - if (entries.size() < other.entries.size()) - for (auto &it : *this) { - auto oit = other.find(it.first); - if (oit == other.end() || oit->second != it.second) - return false; - } - else - for (auto &oit : other) { - auto it = find(oit.first); - if (it == end() || it->second != oit.second) - return false; - } + for (auto &it : entries) { + auto oit = other.find(it.udata.first); + if (oit == other.end() || oit->second != it.udata.second) + return false; + } return true; } @@ -537,14 +464,14 @@ public: return !(*this == other); } - size_t size() const { return counter; } - bool empty() const { return counter == 0; } - void clear() { hashtable.clear(); entries.clear(); init(); } + size_t size() const { return entries.size(); } + bool empty() const { return entries.empty(); } + void clear() { hashtable.clear(); entries.clear(); } - iterator begin() { upd_begin_n(); return iterator(this, begin_n); } + iterator begin() { return iterator(this, int(entries.size())-1); } iterator end() { return iterator(nullptr, -1); } - const_iterator begin() const { ((dict*)this)->upd_begin_n(); return const_iterator(this, begin_n); } + const_iterator begin() const { return const_iterator(this, int(entries.size())-1); } const_iterator end() const { return const_iterator(nullptr, -1); } }; From 429ccb62a1c3ea06345b9c8f1ebd3dcbddc42f4c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 31 Dec 2014 04:19:04 +0100 Subject: [PATCH 235/492] new hashlib::pool<> (derived from new dict) --- kernel/hashlib.h | 386 +++++++++++++++++++---------------------------- 1 file changed, 158 insertions(+), 228 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index a34d194f1..6330841f3 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -289,13 +289,13 @@ class dict public: class iterator { - friend dict; + friend dict; protected: - dict *ptr; + dict *ptr; int index; public: iterator() { } - iterator(dict *ptr, int index) : ptr(ptr), index(index) { } + iterator(dict *ptr, int index) : ptr(ptr), index(index) { } iterator operator++() { index--; return *this; } bool operator==(const iterator &other) const { return index == other.index; } bool operator!=(const iterator &other) const { return index != other.index; } @@ -307,13 +307,13 @@ public: class const_iterator { - friend dict; + friend dict; protected: - const dict *ptr; + const dict *ptr; int index; public: const_iterator() { } - const_iterator(const dict *ptr, int index) : ptr(ptr), index(index) { } + const_iterator(const dict *ptr, int index) : ptr(ptr), index(index) { } const_iterator operator++() { index--; return *this; } bool operator==(const const_iterator &other) const { return index == other.index; } bool operator!=(const const_iterator &other) const { return index != other.index; } @@ -325,24 +325,24 @@ public: { } - dict(const dict &other) + dict(const dict &other) { entries = other.entries; do_rehash(); } - dict(dict &&other) + dict(dict &&other) { swap(other); } - dict &operator=(const dict &other) { + dict &operator=(const dict &other) { entries = other.entries; do_rehash(); return *this; } - dict &operator=(dict &&other) { + dict &operator=(dict &&other) { clear(); swap(other); return *this; @@ -443,13 +443,13 @@ public: return entries[i].udata.second; } - void swap(dict &other) + void swap(dict &other) { hashtable.swap(other.hashtable); entries.swap(other.entries); } - bool operator==(const dict &other) const { + bool operator==(const dict &other) const { if (size() != other.size()) return false; for (auto &it : entries) { @@ -460,7 +460,7 @@ public: return true; } - bool operator!=(const dict &other) const { + bool operator!=(const dict &other) const { return !(*this == other); } @@ -475,54 +475,38 @@ public: const_iterator end() const { return const_iterator(nullptr, -1); } }; +// ******************************************************************************** +// ******************************************************************************** +// ******************************************************************************** +// ******************************************************************************** +// ******************************************************************************** + + template> class pool { struct entry_t { - int link; - K key; + K udata; + int next; - entry_t() : link(-1) { } - entry_t(const K &key) : link(1), key(key) { } - - bool is_free() const { return link < 0; } - int get_next() const { return (link > 0 ? link : -link) - 2; } - bool get_last() const { return get_next() == -1; } - void set_next_used(int next) { link = next + 2; } - void set_next_free(int next) { link = -(next + 2); } + entry_t() { } + entry_t(const K &udata, int next) : udata(udata), next(next) { } }; std::vector hashtable; std::vector entries; - int free_list, counter, begin_n; - int begin_seek_count; OPS ops; - void init() - { - free_list = -1; - counter = 0; - begin_n = -1; - begin_seek_count = 0; +#if 0 + static inline void do_assert(bool cond) { + if (!cond) throw std::runtime_error("pool<> assert failed."); } +#else + static inline void do_assert(bool) { } +#endif - void init_from(const pool &other) - { - hashtable.clear(); - entries.clear(); - - counter = other.size(); - begin_n = counter - 1; - entries.reserve(counter); - - for (auto &it : other) - entries.push_back(entry_t(it)); - - rehash(); - } - - int mkhash(const K &key) const + int do_hash(const K &key) const { unsigned int hash = 0; if (!hashtable.empty()) @@ -530,190 +514,152 @@ class pool return hash; } - void upd_begin_n(bool do_refree = true) + void do_rehash() { - if (begin_n < -1) { - begin_n = -(begin_n+2); - while (begin_n >= 0 && entries[begin_n].is_free()) { begin_seek_count++; begin_n--; } - if (do_refree && begin_seek_count > int(entries.size() / 2)) refree(); - } - } - - void refree() - { - free_list = -1; - begin_n = -1; - - int last_free = -1; - for (int i = 0; i < int(entries.size()); i++) - if (entries[i].is_free()) { - if (last_free != -1) - entries[last_free].set_next_free(i); - else - free_list = i; - last_free = i; - } else - begin_n = i; - - if (last_free != -1) - entries[last_free].set_next_free(-1); - - begin_seek_count = 0; - } - - void rehash() - { - upd_begin_n(false); - entries.resize(begin_n + 1); - - free_list = -1; - begin_n = -1; - hashtable.clear(); hashtable.resize(hashtable_size(entries.size() * hashtable_size_factor), -1); - int last_free = -1; - for (int i = 0; i < int(entries.size()); i++) - if (entries[i].is_free()) { - if (last_free != -1) - entries[last_free].set_next_free(i); - else - free_list = i; - last_free = i; - } else { - int hash = mkhash(entries[i].key); - entries[i].set_next_used(hashtable[hash]); - hashtable[hash] = i; - begin_n = i; - } - - if (last_free != -1) - entries[last_free].set_next_free(-1); - - begin_seek_count = 0; - } - - int do_erase(const K &key, int hash) - { - int last_index = -1; - int index = hashtable.empty() ? -1 : hashtable[hash]; - while (1) { - if (index < 0) - return 0; - if (ops.cmp(entries[index].key, key)) { - if (last_index < 0) - hashtable[hash] = entries[index].get_next(); - else - entries[last_index].set_next_used(entries[index].get_next()); - entries[index].key = K(); - entries[index].set_next_free(free_list); - free_list = index; - if (--counter == 0) - clear(); - else if (index == begin_n) - begin_n = -(begin_n+2); - return 1; - } - last_index = index; - index = entries[index].get_next(); + for (int i = 0; i < int(entries.size()); i++) { + do_assert(-1 <= entries[i].next && entries[i].next < int(entries.size())); + int hash = do_hash(entries[i].udata); + entries[i].next = hashtable[hash]; + hashtable[hash] = i; } } - int lookup_index(const K &key, int hash) const + int do_erase(int index, int hash) { - int index = hashtable.empty() ? -1 : hashtable[hash]; - while (1) { - if (index < 0) - return -1; - if (ops.cmp(entries[index].key, key)) - return index; - index = entries[index].get_next(); - } - } + do_assert(index < int(entries.size())); + if (hashtable.empty() || index < 0) + return 0; - int insert_at(const K &key, int hash) - { - if (free_list < 0) + int k = hashtable[hash]; + if (k == index) { + hashtable[hash] = entries[index].next; + } else { + while (entries[k].next != index) { + k = entries[k].next; + do_assert(0 <= k && k < int(entries.size())); + } + entries[k].next = entries[index].next; + } + + int back_idx = entries.size()-1; + + if (index != back_idx) { - free_list = entries.size(); - entries.push_back(entry_t()); + int back_hash = do_hash(entries[back_idx].udata); - if (entries.size() * hashtable_size_trigger > hashtable.size()) { - int i = free_list; - entries[i].key = key; - entries[i].set_next_used(0); - begin_n = i; - counter++; - rehash(); - return i; + k = hashtable[back_hash]; + if (k == back_idx) { + hashtable[back_hash] = index; + } else { + while (entries[k].next != back_idx) { + k = entries[k].next; + do_assert(0 <= k && k < int(entries.size())); + } + entries[k].next = index; } + + entries[index] = std::move(entries[back_idx]); } - int i = free_list; - free_list = entries[i].get_next(); - entries[i].key = key; - entries[i].set_next_used(hashtable[hash]); - hashtable[hash] = i; - if ((begin_n < -1 && -(begin_n+2) <= i) || (begin_n >= -1 && begin_n <= i)) - begin_n = i; - counter++; - return i; + entries.pop_back(); + + if (entries.empty()) + hashtable.clear(); + + return 1; + } + + int do_lookup(const K &key, int &hash) const + { + if (hashtable.empty()) + return -1; + + if (entries.size() * hashtable_size_trigger > hashtable.size()) { + ((pool*)this)->do_rehash(); + hash = do_hash(key); + } + + int index = hashtable[hash]; + + while (index >= 0 && !ops.cmp(entries[index].udata, key)) { + index = entries[index].next; + do_assert(-1 <= index && index < int(entries.size())); + } + + return index; + } + + int do_insert(const K &value, int &hash) + { + if (hashtable.empty()) { + entries.push_back(entry_t(value, -1)); + do_rehash(); + hash = do_hash(value); + } else { + entries.push_back(entry_t(value, hashtable[hash])); + hashtable[hash] = entries.size() - 1; + } + return entries.size() - 1; } public: class iterator { - pool *ptr; + friend pool; + protected: + pool *ptr; int index; public: iterator() { } - iterator(pool *ptr, int index) : ptr(ptr), index(index) { } - iterator operator++() { do index--; while (index >= 0 && ptr->entries[index].is_free()); return *this; } + iterator(pool *ptr, int index) : ptr(ptr), index(index) { } + iterator operator++() { index--; return *this; } bool operator==(const iterator &other) const { return index == other.index; } bool operator!=(const iterator &other) const { return index != other.index; } - K &operator*() { return ptr->entries[index].key; } - K *operator->() { return &ptr->entries[index].key; } - const K &operator*() const { return ptr->entries[index].key; } - const K *operator->() const { return &ptr->entries[index].key; } + const K &operator*() const { return ptr->entries[index].udata; } + const K *operator->() const { return &ptr->entries[index].udata; } }; class const_iterator { - const pool *ptr; + friend pool; + protected: + const pool *ptr; int index; public: const_iterator() { } - const_iterator(const pool *ptr, int index) : ptr(ptr), index(index) { } - const_iterator operator++() { do index--; while (index >= 0 && ptr->entries[index].is_free()); return *this; } + const_iterator(const pool *ptr, int index) : ptr(ptr), index(index) { } + const_iterator operator++() { index--; return *this; } bool operator==(const const_iterator &other) const { return index == other.index; } bool operator!=(const const_iterator &other) const { return index != other.index; } - const K &operator*() const { return ptr->entries[index].key; } - const K *operator->() const { return &ptr->entries[index].key; } + const K &operator*() const { return ptr->entries[index].udata; } + const K *operator->() const { return &ptr->entries[index].udata; } }; pool() { - init(); } - pool(const pool &other) + pool(const pool &other) { - init_from(other); + entries = other.entries; + do_rehash(); } - pool(pool &&other) + pool(pool &&other) { - init(); swap(other); } - pool &operator=(const pool &other) { - if (this != &other) - init_from(other); + pool &operator=(const pool &other) { + entries = other.entries; + do_rehash(); return *this; } - pool &operator=(pool &&other) { + pool &operator=(pool &&other) { clear(); swap(other); return *this; @@ -721,7 +667,6 @@ public: pool(const std::initializer_list &list) { - init(); for (auto &it : list) insert(it); } @@ -729,7 +674,6 @@ public: template pool(InputIterator first, InputIterator last) { - init(); insert(first, last); } @@ -740,40 +684,41 @@ public: insert(*first); } - std::pair insert(const K &key) + std::pair insert(const K &value) { - int hash = mkhash(key); - int i = lookup_index(key, hash); + int hash = do_hash(value); + int i = do_lookup(value, hash); if (i >= 0) return std::pair(iterator(this, i), false); - i = insert_at(key, hash); + i = do_insert(value, hash); return std::pair(iterator(this, i), true); } int erase(const K &key) { - int hash = mkhash(key); - return do_erase(key, hash); + int hash = do_hash(key); + int index = do_lookup(key, hash); + return do_erase(index, hash); } iterator erase(iterator it) { - int hash = mkhash(*it); - do_erase(*it, hash); + int hash = do_hash(it->first); + do_erase(it.index, hash); return ++it; } int count(const K &key) const { - int hash = mkhash(key); - int i = lookup_index(key, hash); + int hash = do_hash(key); + int i = do_lookup(key, hash); return i < 0 ? 0 : 1; } iterator find(const K &key) { - int hash = mkhash(key); - int i = lookup_index(key, hash); + int hash = do_hash(key); + int i = do_lookup(key, hash); if (i < 0) return end(); return iterator(this, i); @@ -781,62 +726,47 @@ public: const_iterator find(const K &key) const { - int hash = mkhash(key); - int i = lookup_index(key, hash); + int hash = do_hash(key); + int i = do_lookup(key, hash); if (i < 0) return end(); return const_iterator(this, i); } - bool operator[](const K &key) const + bool operator[](const K &key) { - int hash = mkhash(key); - int i = lookup_index(key, hash); + int hash = do_hash(key); + int i = do_lookup(key, hash); return i >= 0; } - void swap(pool &other) + void swap(pool &other) { hashtable.swap(other.hashtable); entries.swap(other.entries); - std::swap(free_list, other.free_list); - std::swap(counter, other.counter); - std::swap(begin_n, other.begin_n); - std::swap(begin_seek_count, other.begin_seek_count); } - bool operator==(const pool &other) const { - if (counter != other.counter) + bool operator==(const pool &other) const { + if (size() != other.size()) return false; - if (counter == 0) - return true; - if (entries.size() < other.entries.size()) - for (auto &it : *this) { - auto oit = other.find(it.first); - if (oit == other.end() || oit->second != it.second) - return false; - } - else - for (auto &oit : other) { - auto it = find(oit.first); - if (it == end() || it->second != oit.second) - return false; - } + for (auto &it : entries) + if (!other.count(it.udata)) + return false; return true; } - bool operator!=(const pool &other) const { + bool operator!=(const pool &other) const { return !(*this == other); } - size_t size() const { return counter; } - bool empty() const { return counter == 0; } - void clear() { hashtable.clear(); entries.clear(); init(); } + size_t size() const { return entries.size(); } + bool empty() const { return entries.empty(); } + void clear() { hashtable.clear(); entries.clear(); } - iterator begin() { upd_begin_n(); return iterator(this, begin_n); } + iterator begin() { return iterator(this, int(entries.size())-1); } iterator end() { return iterator(nullptr, -1); } - const_iterator begin() const { ((pool*)this)->upd_begin_n(); return const_iterator(this, begin_n); } + const_iterator begin() const { return const_iterator(this, int(entries.size())-1); } const_iterator end() const { return const_iterator(nullptr, -1); } }; From 12b05dfc040ccdcde193cd1ff81e97b3c5e2c974 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 31 Dec 2014 04:24:04 +0100 Subject: [PATCH 236/492] gcc-4.6 compile fixes --- kernel/hashlib.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 6330841f3..7f2575d72 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -289,7 +289,7 @@ class dict public: class iterator { - friend dict; + friend class dict; protected: dict *ptr; int index; @@ -307,7 +307,7 @@ public: class const_iterator { - friend dict; + friend class dict; protected: const dict *ptr; int index; @@ -608,7 +608,7 @@ class pool public: class iterator { - friend pool; + friend class pool; protected: pool *ptr; int index; @@ -624,7 +624,7 @@ public: class const_iterator { - friend pool; + friend class pool; protected: const pool *ptr; int index; From b9e412423a681589b35f73412c43b23fee34560f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 31 Dec 2014 13:05:33 +0100 Subject: [PATCH 237/492] hashlib cleanups and a fix --- kernel/hashlib.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 7f2575d72..29f4f68b1 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -49,30 +49,30 @@ inline unsigned int mkhash_xorshift(unsigned int a) { } template struct hash_ops { - bool cmp(const T &a, const T &b) const { + static inline bool cmp(const T &a, const T &b) { return a == b; } - unsigned int hash(const T &a) const { + static inline unsigned int hash(const T &a) { return a.hash(); } }; template<> struct hash_ops { template - bool cmp(T a, T b) const { + static inline bool cmp(T a, T b) { return a == b; } template - unsigned int hash(T a) const { + static inline unsigned int hash(T a) { return a; } }; template<> struct hash_ops { - bool cmp(const std::string &a, const std::string &b) const { + static inline bool cmp(const std::string &a, const std::string &b) { return a == b; } - unsigned int hash(const std::string &a) const { + static inline unsigned int hash(const std::string &a) { unsigned int v = 0; for (auto c : a) v = mkhash(v, c); @@ -81,10 +81,10 @@ template<> struct hash_ops { }; template struct hash_ops> { - bool cmp(std::pair a, std::pair b) const { + static inline bool cmp(std::pair a, std::pair b) { return a == b; } - unsigned int hash(std::pair a) const { + static inline unsigned int hash(std::pair a) { hash_ops

p_ops; hash_ops q_ops; return mkhash(p_ops.hash(a.first), q_ops.hash(a.second)); @@ -92,10 +92,10 @@ template struct hash_ops> { }; template struct hash_ops> { - bool cmp(std::vector a, std::vector b) const { + static inline bool cmp(std::vector a, std::vector b) { return a == b; } - unsigned int hash(std::vector a) const { + static inline unsigned int hash(std::vector a) { hash_ops t_ops; unsigned int h = mkhash_init; for (auto k : a) @@ -105,13 +105,13 @@ template struct hash_ops> { }; struct hash_cstr_ops { - bool cmp(const char *a, const char *b) const { + static inline bool cmp(const char *a, const char *b) { for (int i = 0; a[i] || b[i]; i++) if (a[i] != b[i]) return false; return true; } - unsigned int hash(const char *a) const { + static inline unsigned int hash(const char *a) { unsigned int hash = mkhash_init; while (*a) hash = mkhash(hash, *(a++)); @@ -120,20 +120,20 @@ struct hash_cstr_ops { }; struct hash_ptr_ops { - bool cmp(const void *a, const void *b) const { + static inline bool cmp(const void *a, const void *b) { return a == b; } - unsigned int hash(const void *a) const { + static inline unsigned int hash(const void *a) { return (unsigned long)a; } }; struct hash_obj_ops { - bool cmp(const void *a, const void *b) const { + static inline bool cmp(const void *a, const void *b) { return a == b; } template - unsigned int hash(const T *a) const { + static inline unsigned int hash(const T *a) { return a->hash(); } }; @@ -703,7 +703,7 @@ public: iterator erase(iterator it) { - int hash = do_hash(it->first); + int hash = do_hash(*it); do_erase(it.index, hash); return ++it; } From ba48b6b1e6fb962428c0e4ce4a3f0fb3a5cd59eb Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 31 Dec 2014 13:15:35 +0100 Subject: [PATCH 238/492] improved bitpattern (proc_mux) performance --- kernel/bitpattern.h | 65 ++++++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/kernel/bitpattern.h b/kernel/bitpattern.h index 7416a488d..00bbc3bfb 100644 --- a/kernel/bitpattern.h +++ b/kernel/bitpattern.h @@ -28,14 +28,34 @@ YOSYS_NAMESPACE_BEGIN struct BitPatternPool { int width; - typedef std::vector bits_t; + struct bits_t { + std::vector bitdata; + unsigned int cached_hash; + bits_t(int width = 0) : bitdata(width), cached_hash(0) { } + RTLIL::State &operator[](int index) { + return bitdata[index]; + } + const RTLIL::State &operator[](int index) const { + return bitdata[index]; + } + bool operator==(const bits_t &other) const { + if (hash() != other.hash()) + return false; + return bitdata == other.bitdata; + } + unsigned int hash() const { + if (!cached_hash) + ((bits_t*)this)->cached_hash = hash_ops>::hash(bitdata); + return cached_hash; + } + }; pool database; BitPatternPool(RTLIL::SigSpec sig) { width = sig.size(); if (width > 0) { - std::vector pattern(width); + bits_t pattern(width); for (int i = 0; i < width; i++) { if (sig[i].wire == NULL && sig[i].data <= RTLIL::State::S1) pattern[i] = sig[i].data; @@ -50,7 +70,7 @@ struct BitPatternPool { this->width = width; if (width > 0) { - std::vector pattern(width); + bits_t pattern(width); for (int i = 0; i < width; i++) pattern[i] = RTLIL::State::Sa; database.insert(pattern); @@ -59,8 +79,9 @@ struct BitPatternPool bits_t sig2bits(RTLIL::SigSpec sig) { - bits_t bits = sig.as_const().bits; - for (auto &b : bits) + bits_t bits; + bits.bitdata = sig.as_const().bits; + for (auto &b : bits.bitdata) if (b > RTLIL::State::S1) b = RTLIL::State::Sa; return bits; @@ -68,8 +89,8 @@ struct BitPatternPool bool match(bits_t a, bits_t b) { - log_assert(int(a.size()) == width); - log_assert(int(b.size()) == width); + log_assert(int(a.bitdata.size()) == width); + log_assert(int(b.bitdata.size()) == width); for (int i = 0; i < width; i++) if (a[i] <= RTLIL::State::S1 && b[i] <= RTLIL::State::S1 && a[i] != b[i]) return false; @@ -103,21 +124,21 @@ struct BitPatternPool { bool status = false; bits_t bits = sig2bits(sig); - std::vector pattern_list; - for (auto &it : database) - if (match(it, bits)) - pattern_list.push_back(it); - for (auto pattern : pattern_list) { - database.erase(pattern); - for (int i = 0; i < width; i++) { - if (pattern[i] != RTLIL::State::Sa || bits[i] == RTLIL::State::Sa) - continue; - bits_t new_pattern = pattern; - new_pattern[i] = bits[i] == RTLIL::State::S1 ? RTLIL::State::S0 : RTLIL::State::S1; - database.insert(new_pattern); - } - status = true; - } + for (auto it = database.begin(); it != database.end();) + if (match(*it, bits)) { + for (int i = 0; i < width; i++) { + if ((*it)[i] != RTLIL::State::Sa || bits[i] == RTLIL::State::Sa) + continue; + bits_t new_pattern; + new_pattern.bitdata = it->bitdata; + new_pattern[i] = bits[i] == RTLIL::State::S1 ? RTLIL::State::S0 : RTLIL::State::S1; + database.insert(new_pattern); + } + it = database.erase(it); + status = true; + continue; + } else + ++it; return status; } From 539dd805f44ece3e39f4c68e4ea1bdc9b662e83f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 31 Dec 2014 14:26:54 +0100 Subject: [PATCH 239/492] Improvements in CodingReadme --- CodingReadme | 33 ++++++++++++++++++++++++--------- manual/CHAPTER_Prog.tex | 21 +++++++++++++-------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/CodingReadme b/CodingReadme index bdadf821d..2349b2ee2 100644 --- a/CodingReadme +++ b/CodingReadme @@ -1,5 +1,10 @@ +This file contains some very brief documentation on things like programming APIs. +Also consult the Yosys manual and the section about programming in the presentation. +(Both can be downloaded as PDF from the yosys webpage.) + +--snip-- only the lines below this mark are included in the yosys manual --snip-- Getting Started =============== @@ -42,13 +47,21 @@ defined when "kernel/yosys.h" is included and USING_YOSYS_NAMESPACE is used. 1. Yosys Container Classes Yosys uses dict and pool as main container classes. dict is -essentially a replacement for std::unordered_map and pool is -essentially a replacement for std::unordered_set. The main differences are: +essentially a replacement for std::unordered_map and pool is a +replacement for std::unordered_set. The main characteristics are: - dict and pool are about 2x faster than the std containers - references to elements in a dict or pool are invalidated by - insert operations (just like you are used from std::vector). + insert and remove operations (similar to std::vector on push_back()). + + - some iterators are invalidated by erase(). specifically, iterators + that have not passed the erased element yet are invalidated. (erase() + itself returns valid iterator to the next element.) + + - no iterators are invalidated by insert(). elements are inserted at + begin(). i.e. only a new iterator that starts at begin() will see the + inserted elements. - dict and pool will have the same order of iteration across all compilers and architectures. @@ -97,12 +110,12 @@ namespace. 4. SigMap and other Helper Classes There are a couple of additional helper classes that are in wide use -in Yosys. Most importantly there is SigMap (declared in kernel.sigtools.h). +in Yosys. Most importantly there is SigMap (declared in kernel/sigtools.h). -When a design has many wires in it that are connected to each other, then -a single signal bit can have multiple valid names. The SigMap object can -be used to map SigSpecs or SigBits to unique SigSpecs and SigBits that -consitently only uses one wire from a group of connected wires. For example: +When a design has many wires in it that are connected to each other, then a +single signal bit can have multiple valid names. The SigMap object can be used +to map SigSpecs or SigBits to unique SigSpecs and SigBits that consitently +only use one wire from such a group of connected wires. For example: SigBit a = module->addWire(NEW_ID); SigBit b = module->addWire(NEW_ID); @@ -162,7 +175,7 @@ C++ Langugage ------------- Yosys is written in C++11. At the moment only constructs supported by -gcc 4.6 is allowed in Yosys code. This will change in future releases. +gcc 4.6 are allowed in Yosys code. This will change in future releases. In general Yosys uses "int" instead of "size_t". To avoid compiler warnings for implicit type casts, always use "GetSize(foobar)" instead @@ -171,6 +184,8 @@ of "foobar.size()". (GetSize() is defined in kernel/yosys.h) Use range-based for loops whenever applicable. +--snap-- only the lines above this mark are included in the yosys manual --snap-- + Creating the Visual Studio Template Project =========================================== diff --git a/manual/CHAPTER_Prog.tex b/manual/CHAPTER_Prog.tex index 3918594a2..3cbc95a19 100644 --- a/manual/CHAPTER_Prog.tex +++ b/manual/CHAPTER_Prog.tex @@ -2,16 +2,21 @@ \chapter{Programming Yosys Extensions} \label{chapter:prog} -\begin{fixme} -This chapter will contain a guided tour to the Yosys APIs and conclude -with an example module. -\end{fixme} +This chapter contains some bits and pieces of information about programming +yosys extensions. Also consult the section on programming in the ``Yosys +Presentation'' (can be downloaded from the Yosys website as PDF) and don't +be afraid to ask questions on the Yosys Subreddit. -\section{Programming with RTLIL} -\section{Internal Utility Libraries} -\section{Loadable Modules} +\section{The ``CodingReadme'' File} + +The following is an excerpt of the {\tt CodingReadme} file from the Yosys source tree. + +\lstinputlisting[title=CodingReadme,rangeprefix=--,rangesuffix=--,includerangemarker=false,linerange=snip-snap,numbers=left,frame=single]{../CodingReadme} + +\section{The ``stubsnets'' Example Module} + +The following is the complete code of the ``stubsnets'' example module. It is included in the Yosys source distribution as {\tt manual/CHAPTER\_Prog/stubnets.cc}. -\section{Example Module} \lstinputlisting[title=stubnets.cc,numbers=left,frame=single,language=C++]{CHAPTER_Prog/stubnets.cc} From 1e08621e7e2c219169b3b6c5fe1d581052e4d429 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 31 Dec 2014 14:52:46 +0100 Subject: [PATCH 240/492] Added hashlib .count(key, iterator) and it1 < it2 --- CodingReadme | 8 +++- kernel/hashlib.h | 99 +++++++++++++++++++++++++++--------------------- 2 files changed, 63 insertions(+), 44 deletions(-) diff --git a/CodingReadme b/CodingReadme index 2349b2ee2..92d54d283 100644 --- a/CodingReadme +++ b/CodingReadme @@ -63,8 +63,14 @@ replacement for std::unordered_set. The main characteristics are: begin(). i.e. only a new iterator that starts at begin() will see the inserted elements. + - the method .count(key, iterator) is like .count(key) but only + considers elements that can be reached via the iterator. + + - iterators can be compared. it1 < it2 means that the position of t2 + can be reached via t1 but not vice versa. + - dict and pool will have the same order of iteration across - all compilers and architectures. + all compilers, standard libraries and architectures. 2. Standard STL data types diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 29f4f68b1..5e00e89d6 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -287,40 +287,43 @@ class dict } public: - class iterator - { - friend class dict; - protected: - dict *ptr; - int index; - public: - iterator() { } - iterator(dict *ptr, int index) : ptr(ptr), index(index) { } - iterator operator++() { index--; return *this; } - bool operator==(const iterator &other) const { return index == other.index; } - bool operator!=(const iterator &other) const { return index != other.index; } - std::pair &operator*() { return ptr->entries[index].udata; } - std::pair *operator->() { return &ptr->entries[index].udata; } - const std::pair &operator*() const { return ptr->entries[index].udata; } - const std::pair *operator->() const { return &ptr->entries[index].udata; } - }; - class const_iterator { friend class dict; protected: const dict *ptr; int index; + const_iterator(const dict *ptr, int index) : ptr(ptr), index(index) { } public: const_iterator() { } - const_iterator(const dict *ptr, int index) : ptr(ptr), index(index) { } const_iterator operator++() { index--; return *this; } + bool operator<(const const_iterator &other) const { return index > other.index; } bool operator==(const const_iterator &other) const { return index == other.index; } bool operator!=(const const_iterator &other) const { return index != other.index; } const std::pair &operator*() const { return ptr->entries[index].udata; } const std::pair *operator->() const { return &ptr->entries[index].udata; } }; + class iterator + { + friend class dict; + protected: + dict *ptr; + int index; + iterator(dict *ptr, int index) : ptr(ptr), index(index) { } + public: + iterator() { } + iterator operator++() { index--; return *this; } + bool operator<(const iterator &other) const { return index > other.index; } + bool operator==(const iterator &other) const { return index == other.index; } + bool operator!=(const iterator &other) const { return index != other.index; } + std::pair &operator*() { return ptr->entries[index].udata; } + std::pair *operator->() { return &ptr->entries[index].udata; } + const std::pair &operator*() const { return ptr->entries[index].udata; } + const std::pair *operator->() const { return &ptr->entries[index].udata; } + operator const_iterator() const { return const_iterator(ptr, index); } + }; + dict() { } @@ -398,6 +401,13 @@ public: return i < 0 ? 0 : 1; } + int count(const K &key, const_iterator it) const + { + int hash = do_hash(key); + int i = do_lookup(key, hash); + return i < 0 || i > it.index ? 0 : 1; + } + iterator find(const K &key) { int hash = do_hash(key); @@ -475,13 +485,6 @@ public: const_iterator end() const { return const_iterator(nullptr, -1); } }; -// ******************************************************************************** -// ******************************************************************************** -// ******************************************************************************** -// ******************************************************************************** -// ******************************************************************************** - - template> class pool { @@ -606,31 +609,15 @@ class pool } public: - class iterator - { - friend class pool; - protected: - pool *ptr; - int index; - public: - iterator() { } - iterator(pool *ptr, int index) : ptr(ptr), index(index) { } - iterator operator++() { index--; return *this; } - bool operator==(const iterator &other) const { return index == other.index; } - bool operator!=(const iterator &other) const { return index != other.index; } - const K &operator*() const { return ptr->entries[index].udata; } - const K *operator->() const { return &ptr->entries[index].udata; } - }; - class const_iterator { friend class pool; protected: const pool *ptr; int index; + const_iterator(const pool *ptr, int index) : ptr(ptr), index(index) { } public: const_iterator() { } - const_iterator(const pool *ptr, int index) : ptr(ptr), index(index) { } const_iterator operator++() { index--; return *this; } bool operator==(const const_iterator &other) const { return index == other.index; } bool operator!=(const const_iterator &other) const { return index != other.index; } @@ -638,6 +625,25 @@ public: const K *operator->() const { return &ptr->entries[index].udata; } }; + class iterator + { + friend class pool; + protected: + pool *ptr; + int index; + iterator(pool *ptr, int index) : ptr(ptr), index(index) { } + public: + iterator() { } + iterator operator++() { index--; return *this; } + bool operator==(const iterator &other) const { return index == other.index; } + bool operator!=(const iterator &other) const { return index != other.index; } + K &operator*() { return ptr->entries[index].udata; } + K *operator->() { return &ptr->entries[index].udata; } + const K &operator*() const { return ptr->entries[index].udata; } + const K *operator->() const { return &ptr->entries[index].udata; } + operator const_iterator() const { return const_iterator(ptr, index); } + }; + pool() { } @@ -715,6 +721,13 @@ public: return i < 0 ? 0 : 1; } + int count(const K &key, const_iterator it) const + { + int hash = do_hash(key); + int i = do_lookup(key, hash); + return i < 0 || i > it.index ? 0 : 1; + } + iterator find(const K &key) { int hash = do_hash(key); From 94e6b70736934bd8ebb09c7cc74cfd443bd1d9eb Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 31 Dec 2014 16:53:53 +0100 Subject: [PATCH 241/492] Added memory_bram (not functional yet) --- kernel/yosys.h | 2 +- passes/memory/Makefile.inc | 1 + passes/memory/memory_bram.cc | 285 +++++++++++++++++++++++++++++++++++ techlibs/xilinx/brams.txt | 20 +++ 4 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 passes/memory/memory_bram.cc create mode 100644 techlibs/xilinx/brams.txt diff --git a/kernel/yosys.h b/kernel/yosys.h index 2c9ca0dd9..88f060a52 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -199,7 +199,7 @@ inline void memhasher() { if (memhasher_active) memhasher_do(); } std::string stringf(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 1, 2)); std::string vstringf(const char *fmt, va_list ap); int readsome(std::istream &f, char *s, int n); -std::string next_token(std::string &text, const char *sep); +std::string next_token(std::string &text, const char *sep = " \t\r\n"); bool patmatch(const char *pattern, const char *string); int run_command(const std::string &command, std::function process_line = std::function()); std::string make_temp_file(std::string template_str = "/tmp/yosys_XXXXXX"); diff --git a/passes/memory/Makefile.inc b/passes/memory/Makefile.inc index 026c5ff85..aeff225d8 100644 --- a/passes/memory/Makefile.inc +++ b/passes/memory/Makefile.inc @@ -4,5 +4,6 @@ OBJS += passes/memory/memory_dff.o OBJS += passes/memory/memory_share.o OBJS += passes/memory/memory_collect.o OBJS += passes/memory/memory_unpack.o +OBJS += passes/memory/memory_bram.o OBJS += passes/memory/memory_map.o diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc new file mode 100644 index 000000000..9c02866e9 --- /dev/null +++ b/passes/memory/memory_bram.cc @@ -0,0 +1,285 @@ +/* + * 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" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct rules_t +{ + struct bram_t { + IdString name; + int groups, abits, dbits, init; + vector wports, rports, wenabl, transp, clocks, clkpol; + }; + + struct match_t { + IdString name; + dict min_limits, max_limits; + }; + + dict brams; + vector matches; + + std::ifstream infile; + vector tokens; + int linecount; + string line; + + void syntax_error() + { + if (line.empty()) + log_error("Unexpected end of rules file in line %d.\n", linecount); + log_error("Syntax error in rules file line %d: %s\n", linecount, line.c_str()); + } + + bool next_line() + { + linecount++; + tokens.clear(); + while (std::getline(infile, line)) { + for (string tok = next_token(line); !tok.empty(); tok = next_token(line)) { + if (tok[0] == '#') + break; + tokens.push_back(tok); + } + if (!tokens.empty()) + return true; + } + return false; + } + + bool parse_single_int(const char *stmt, int &value) + { + if (GetSize(tokens) == 2 && tokens[0] == stmt) { + value = atoi(tokens[1].c_str()); + return true; + } + return false; + } + + bool parse_int_vect(const char *stmt, vector &value) + { + if (GetSize(tokens) >= 2 && tokens[0] == stmt) { + value.resize(GetSize(tokens)-1); + for (int i = 1; i < GetSize(tokens); i++) + value[i] = atoi(tokens[i].c_str()); + return true; + } + return false; + } + + void parse_bram() + { + if (GetSize(tokens) != 2) + syntax_error(); + + bram_t data; + data.name = RTLIL::escape_id(tokens[1]); + + while (next_line()) + { + if (GetSize(tokens) == 1 && tokens[0] == "endbram") { + brams[data.name] = data; + return; + } + + if (parse_single_int("groups", data.groups)) + continue; + + if (parse_single_int("abits", data.abits)) + continue; + + if (parse_single_int("dbits", data.dbits)) + continue; + + if (parse_single_int("init", data.init)) + continue; + + if (parse_int_vect("wports", data.wports)) + continue; + + if (parse_int_vect("rports", data.rports)) + continue; + + if (parse_int_vect("wenabl", data.wenabl)) + continue; + + if (parse_int_vect("transp", data.transp)) + continue; + + if (parse_int_vect("clocks", data.clocks)) + continue; + + if (parse_int_vect("clkpol", data.clkpol)) + continue; + + break; + } + + syntax_error(); + } + + void parse_match() + { + if (GetSize(tokens) != 2) + syntax_error(); + + match_t data; + data.name = RTLIL::escape_id(tokens[1]); + + while (next_line()) + { + if (GetSize(tokens) == 1 && tokens[0] == "endmatch") { + matches.push_back(data); + return; + } + + if (GetSize(tokens) == 3 && tokens[0] == "min") { + data.min_limits[tokens[1]] = atoi(tokens[2].c_str()); + continue; + } + + if (GetSize(tokens) == 3 && tokens[0] == "max") { + data.max_limits[tokens[1]] = atoi(tokens[2].c_str()); + continue; + } + + break; + } + + syntax_error(); + } + + void parse(std::string filename) + { + infile.open(filename); + linecount = 0; + + if (infile.fail()) + log_error("Can't open rules file `%s'.\n", filename.c_str()); + + while (next_line()) + { + if (tokens[0] == "bram") parse_bram(); + else if (tokens[0] == "match") parse_match(); + else syntax_error(); + } + + infile.close(); + } +}; + +void replace_cell(Cell*, const rules_t::bram_t&, const rules_t::match_t&) +{ + log(" FIXME: The core of memory_bram is not implemented yet.\n"); +} + +void handle_cell(Cell *cell, const rules_t &rules) +{ + log("Processing %s.%s:\n", log_id(cell->module), log_id(cell)); + + dict mem_properties; + mem_properties["words"] = cell->getParam("\\SIZE").as_int(); + mem_properties["abits"] = cell->getParam("\\ABITS").as_int(); + mem_properties["dbits"] = cell->getParam("\\WIDTH").as_int(); + mem_properties["wports"] = cell->getParam("\\WR_PORTS").as_int(); + mem_properties["rports"] = cell->getParam("\\RD_PORTS").as_int(); + mem_properties["bits"] = mem_properties["words"] * mem_properties["dbits"]; + mem_properties["ports"] = mem_properties["wports"] + mem_properties["rports"]; + + log(" Properties:"); + for (auto &it : mem_properties) + log(" %s=%d", it.first.c_str(), it.second); + log("\n"); + + for (int i = 0; i < GetSize(rules.matches); i++) + { + for (auto it : rules.matches[i].min_limits) { + if (!mem_properties.count(it.first)) + log_error("Unknown property '%s' in match rule for bram type %s.\n", + it.first.c_str(), log_id(rules.matches[i].name)); + if (mem_properties[it.first] >= it.second) + continue; + log(" Rule #%d for bram type %s rejected: requirement 'min %s %d' not met.\n", + i, log_id(rules.matches[i].name), it.first.c_str(), it.second); + goto next_match_rule; + } + for (auto it : rules.matches[i].max_limits) { + if (!mem_properties.count(it.first)) + log_error("Unknown property '%s' in match rule for bram type %s.\n", + it.first.c_str(), log_id(rules.matches[i].name)); + if (mem_properties[it.first] <= it.second) + continue; + log(" Rule #%d for bram type %s rejected: requirement 'max %s %d' not met.\n", + i, log_id(rules.matches[i].name), it.first.c_str(), it.second); + goto next_match_rule; + } + + log(" Rule #%d for bram type %s accepted.\n", i, log_id(rules.matches[i].name)); + if (!rules.brams.count(rules.matches[i].name)) + log_error("No bram description for resource %s found!\n", log_id(rules.matches[i].name)); + + replace_cell(cell, rules.brams.at(rules.matches[i].name), rules.matches[i]); + return; + + next_match_rule:; + } + + log(" No acceptable bram resources found.\n"); +} + +struct MemoryBramPass : public Pass { + MemoryBramPass() : Pass("memory_bram", "map memories to block rams") { } + virtual void help() + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" memory_bram -rules [selection]\n"); + log("\n"); + log("This pass converts the multi-port $mem memory cells into block ram instances.\n"); + log("The given rules file describes the available resources and how they should be\n"); + log("used.\n"); + log("\n"); + } + virtual void execute(vector args, Design *design) + { + rules_t rules; + + log_header("Executing MEMORY_BRAM pass (mapping $mem cells to block memories).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-rules" && argidx+1 < args.size()) { + rules.parse(args[++argidx]); + continue; + } + break; + } + extra_args(args, argidx, design); + + for (auto mod : design->selected_modules()) + for (auto cell : mod->selected_cells()) + if (cell->type == "$mem") + handle_cell(cell, rules); + } +} MemoryBramPass; + +PRIVATE_NAMESPACE_END diff --git a/techlibs/xilinx/brams.txt b/techlibs/xilinx/brams.txt new file mode 100644 index 000000000..03bd2b2b3 --- /dev/null +++ b/techlibs/xilinx/brams.txt @@ -0,0 +1,20 @@ + +# This is a very simplified description of the capabilities of +# the Xilinx RAMB36 core. But it is a start.. +# +bram XILINX_RAMB36_SDP32 + init 1 + abits 10 + dbits 32 + groups 2 + wports 1 0 + rports 0 1 + wenabl 2 0 + transp 0 2 + clocks 1 2 +endbram + +match XILINX_RAMB36_SDP32 + min bits 1024 +endmatch + From 327a5d42b6b396f1c210f1579d03a0806a261d84 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 31 Dec 2014 22:50:08 +0100 Subject: [PATCH 242/492] Progress in memory_bram --- kernel/rtlil.h | 10 +-- kernel/yosys.h | 4 ++ passes/memory/memory_bram.cc | 122 +++++++++++++++++++++++++++++++++-- techlibs/xilinx/brams.txt | 6 +- 4 files changed, 127 insertions(+), 15 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index c40af88aa..7618780b0 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -250,14 +250,14 @@ namespace RTLIL // of cell types). the following functions helps with that. template - bool in(T first, Args... rest) { + bool in(T first, Args... rest) const { return in(first) || in(rest...); } - bool in(IdString rhs) { return *this == rhs; } - bool in(const char *rhs) { return *this == rhs; } - bool in(const std::string &rhs) { return *this == rhs; } - bool in(const pool &rhs) { return rhs.count(*this) != 0; } + bool in(IdString rhs) const { return *this == rhs; } + bool in(const char *rhs) const { return *this == rhs; } + bool in(const std::string &rhs) const { return *this == rhs; } + bool in(const pool &rhs) const { return rhs.count(*this) != 0; } }; static inline std::string escape_id(std::string str) { diff --git a/kernel/yosys.h b/kernel/yosys.h index 88f060a52..d1e01b19c 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -137,6 +137,8 @@ YOSYS_NAMESPACE_BEGIN using std::vector; using std::string; +using std::pair; + using hashlib::mkhash; using hashlib::mkhash_init; using hashlib::mkhash_add; @@ -221,6 +223,8 @@ YOSYS_NAMESPACE_END YOSYS_NAMESPACE_BEGIN +using RTLIL::State; + namespace hashlib { template<> struct hash_ops : hash_ops {}; } diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 9c02866e9..1d50a9bea 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -24,10 +24,33 @@ PRIVATE_NAMESPACE_BEGIN struct rules_t { + struct portinfo_t { + int group, index; + int wrmode, enable, transp, clocks, clkpol; + }; + struct bram_t { IdString name; int groups, abits, dbits, init; - vector wports, rports, wenabl, transp, clocks, clkpol; + vector ports, wrmode, enable, transp, clocks, clkpol; + + vector make_portinfos() const + { + vector portinfos; + for (int i = 0; i < groups && i < GetSize(ports); i++) + for (int j = 0; j < ports[i]; j++) { + portinfo_t pi; + pi.group = i; + pi.index = j; + pi.wrmode = i < GetSize(wrmode) ? wrmode[i] : 0; + pi.enable = i < GetSize(enable) ? enable[i] : 0; + pi.transp = i < GetSize(transp) ? transp[i] : 0; + pi.clocks = i < GetSize(clocks) ? clocks[i] : 0; + pi.clkpol = i < GetSize(clkpol) ? clkpol[i] : 0; + portinfos.push_back(pi); + } + return portinfos; + } }; struct match_t { @@ -80,7 +103,7 @@ struct rules_t if (GetSize(tokens) >= 2 && tokens[0] == stmt) { value.resize(GetSize(tokens)-1); for (int i = 1; i < GetSize(tokens); i++) - value[i] = atoi(tokens[i].c_str()); + value[i-1] = atoi(tokens[i].c_str()); return true; } return false; @@ -113,13 +136,13 @@ struct rules_t if (parse_single_int("init", data.init)) continue; - if (parse_int_vect("wports", data.wports)) + if (parse_int_vect("ports", data.ports)) continue; - if (parse_int_vect("rports", data.rports)) + if (parse_int_vect("wrmode", data.wrmode)) continue; - if (parse_int_vect("wenabl", data.wenabl)) + if (parse_int_vect("enable", data.enable)) continue; if (parse_int_vect("transp", data.transp)) @@ -187,9 +210,85 @@ struct rules_t } }; -void replace_cell(Cell*, const rules_t::bram_t&, const rules_t::match_t&) +bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_t&) { + auto portinfos = bram.make_portinfos(); + dict> clock_domains; + vector mapped_wr_ports; + + log(" Mapping to bram type %s:\n", log_id(bram.name)); + + int wr_ports_n = cell->getParam("\\WR_PORTS").as_int(); + auto wr_clken = SigSpec(cell->getParam("\\WR_CLK_ENABLE")); + auto wr_clkpol = SigSpec(cell->getParam("\\WR_CLK_POLARITY")); + wr_clken.extend_u0(wr_ports_n); + wr_clkpol.extend_u0(wr_ports_n); + + SigSpec wr_clk = cell->getPort("\\WR_CLK"); + SigSpec wr_en = cell->getPort("\\WR_EN"); + + for (int cell_port_i = 0, bram_port_i = 0; cell_port_i < wr_ports_n; cell_port_i++) + { + bool clken = wr_clken[cell_port_i] == State::S1; + auto clkpol = wr_clkpol[cell_port_i] == State::S1; + auto clksig = wr_clk[cell_port_i]; + + pair clkdom(clksig, clkpol); + if (!clken) + clkdom = pair(State::S1, false); + + log(" Write port #%d is in clock domain %s%s.\n", + cell_port_i, clkdom.second ? "" : "!", + clken ? log_signal(clkdom.first) : "~async~"); + + for (; bram_port_i < GetSize(portinfos); bram_port_i++) + { + auto &pi = portinfos[bram_port_i]; + + if (pi.wrmode != 1) + skip_bram_wport: + continue; + + if (clken) { + if (pi.clocks == 0) { + log(" Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1); + goto skip_bram_wport; + } + if (clock_domains.count(pi.clocks) && clock_domains.at(pi.clocks) != clkdom) { + log(" Bram port %c%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1); + goto skip_bram_wport; + } + } else { + if (pi.clocks != 0) { + log(" Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1); + goto skip_bram_wport; + } + } + + SigBit last_en_bit = State::S1; + for (int i = 0; i < bram.dbits; i++) { + if (pi.enable && i % (bram.dbits / pi.enable) == 0) + last_en_bit = wr_en[i]; + if (last_en_bit != wr_en[i]) { + log(" Bram port %c%d has incompatible enable structure.\n", pi.group + 'A', pi.index + 1); + goto skip_bram_wport; + } + } + + log(" Mapped to bram port %c%d.\n", pi.group + 'A', pi.index + 1); + if (clken) + clock_domains[pi.clocks] = clkdom; + mapped_wr_ports.push_back(bram_port_i); + goto mapped_port; + } + + log(" Failed to map write port #%d.\n", cell_port_i); + return false; + mapped_port:; + } + log(" FIXME: The core of memory_bram is not implemented yet.\n"); + return false; } void handle_cell(Cell *cell, const rules_t &rules) @@ -210,8 +309,13 @@ void handle_cell(Cell *cell, const rules_t &rules) log(" %s=%d", it.first.c_str(), it.second); log("\n"); + pool failed_brams; + for (int i = 0; i < GetSize(rules.matches); i++) { + if (rules.matches[i].name.in(failed_brams)) + continue; + for (auto it : rules.matches[i].min_limits) { if (!mem_properties.count(it.first)) log_error("Unknown property '%s' in match rule for bram type %s.\n", @@ -237,7 +341,11 @@ void handle_cell(Cell *cell, const rules_t &rules) if (!rules.brams.count(rules.matches[i].name)) log_error("No bram description for resource %s found!\n", log_id(rules.matches[i].name)); - replace_cell(cell, rules.brams.at(rules.matches[i].name), rules.matches[i]); + if (!replace_cell(cell, rules.brams.at(rules.matches[i].name), rules.matches[i])) { + log(" Mapping to bram type %s failed.\n", log_id(rules.matches[i].name)); + failed_brams.insert(rules.matches[i].name); + goto next_match_rule; + } return; next_match_rule:; diff --git a/techlibs/xilinx/brams.txt b/techlibs/xilinx/brams.txt index 03bd2b2b3..e5652eabf 100644 --- a/techlibs/xilinx/brams.txt +++ b/techlibs/xilinx/brams.txt @@ -7,9 +7,9 @@ bram XILINX_RAMB36_SDP32 abits 10 dbits 32 groups 2 - wports 1 0 - rports 0 1 - wenabl 2 0 + ports 1 1 + wrmode 1 0 + enable 4 0 transp 0 2 clocks 1 2 endbram From e62d838bd424995d2fcdc9cef1f56752905c3b4d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 1 Jan 2015 11:41:52 +0100 Subject: [PATCH 243/492] Removed SigSpec::extend_xx() api --- kernel/rtlil.cc | 18 ------------------ kernel/rtlil.h | 1 - passes/proc/proc_arst.cc | 2 +- 3 files changed, 1 insertion(+), 20 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index cd2232c8c..d396d6c24 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2673,24 +2673,6 @@ void RTLIL::SigSpec::append_bit(const RTLIL::SigBit &bit) check(); } -void RTLIL::SigSpec::extend_xx(int width, bool is_signed) -{ - cover("kernel.rtlil.sigspec.extend_xx"); - - pack(); - - if (width_ > width) - remove(width, width_ - width); - - if (width_ < width) { - RTLIL::SigBit padding = width_ > 0 ? (*this)[width_ - 1] : RTLIL::State::S0; - if (!is_signed && (padding == RTLIL::State::S1 || padding.wire)) - padding = RTLIL::State::S0; - while (width_ < width) - append(padding); - } -} - void RTLIL::SigSpec::extend_u0(int width, bool is_signed) { cover("kernel.rtlil.sigspec.extend_u0"); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 7618780b0..53ee24c22 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -651,7 +651,6 @@ public: void append(const RTLIL::SigSpec &signal); void append_bit(const RTLIL::SigBit &bit); - void extend_xx(int width, bool is_signed = false); void extend_u0(int width, bool is_signed = false); RTLIL::SigSpec repeat(int num) const; diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index 0874d0981..27c6b3bcf 100644 --- a/passes/proc/proc_arst.cc +++ b/passes/proc/proc_arst.cc @@ -262,7 +262,7 @@ struct ProcArstPass : public Pass { for (auto &chunk : act.first.chunks()) if (chunk.wire && chunk.wire->attributes.count("\\init")) { RTLIL::SigSpec value = chunk.wire->attributes.at("\\init"); - value.extend_xx(chunk.wire->width, false); + value.extend_u0(chunk.wire->width, false); arst_sig.append(chunk); arst_val.append(value.extract(chunk.offset, chunk.width)); } From 17c1c5547365ae9ec58a1600a67c2b878449de1f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 1 Jan 2015 12:17:19 +0100 Subject: [PATCH 244/492] Progress in memory_bram --- passes/memory/memory_bram.cc | 202 +++++++++++++++++++++++++++-------- 1 file changed, 155 insertions(+), 47 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 1d50a9bea..ee6a35621 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -214,20 +214,41 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ { auto portinfos = bram.make_portinfos(); dict> clock_domains; - vector mapped_wr_ports; + vector mapped_wr_ports, mapped_rd_ports; + dict used_rd_ports; + int rd_port_dups = 1; log(" Mapping to bram type %s:\n", log_id(bram.name)); - int wr_ports_n = cell->getParam("\\WR_PORTS").as_int(); + int mem_size = cell->getParam("\\SIZE").as_int(); + int mem_abits = cell->getParam("\\ABITS").as_int(); + int mem_width = cell->getParam("\\WIDTH").as_int(); + int mem_offset = cell->getParam("\\OFFSET").as_int(); + + int wr_ports = cell->getParam("\\WR_PORTS").as_int(); auto wr_clken = SigSpec(cell->getParam("\\WR_CLK_ENABLE")); auto wr_clkpol = SigSpec(cell->getParam("\\WR_CLK_POLARITY")); - wr_clken.extend_u0(wr_ports_n); - wr_clkpol.extend_u0(wr_ports_n); + wr_clken.extend_u0(wr_ports); + wr_clkpol.extend_u0(wr_ports); - SigSpec wr_clk = cell->getPort("\\WR_CLK"); SigSpec wr_en = cell->getPort("\\WR_EN"); + SigSpec wr_clk = cell->getPort("\\WR_CLK"); + SigSpec wr_data = cell->getPort("\\WR_DATA"); + SigSpec wr_addr = cell->getPort("\\WR_ADDR"); - for (int cell_port_i = 0, bram_port_i = 0; cell_port_i < wr_ports_n; cell_port_i++) + int rd_ports = cell->getParam("\\RD_PORTS").as_int(); + auto rd_clken = SigSpec(cell->getParam("\\RD_CLK_ENABLE")); + auto rd_clkpol = SigSpec(cell->getParam("\\RD_CLK_POLARITY")); + auto rd_transp = SigSpec(cell->getParam("\\RD_TRANSPARENT")); + rd_clken.extend_u0(rd_ports); + rd_clkpol.extend_u0(rd_ports); + rd_transp.extend_u0(rd_ports); + + SigSpec rd_clk = cell->getPort("\\RD_CLK"); + SigSpec rd_data = cell->getPort("\\RD_DATA"); + SigSpec rd_addr = cell->getPort("\\RD_ADDR"); + + for (int cell_port_i = 0, bram_port_i = 0; cell_port_i < wr_ports; cell_port_i++) { bool clken = wr_clken[cell_port_i] == State::S1; auto clkpol = wr_clkpol[cell_port_i] == State::S1; @@ -279,15 +300,84 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ if (clken) clock_domains[pi.clocks] = clkdom; mapped_wr_ports.push_back(bram_port_i); - goto mapped_port; + goto mapped_wr_port; } - log(" Failed to map write port #%d.\n", cell_port_i); + log(" Failed to map write port #%d.\n", cell_port_i); return false; - mapped_port:; + mapped_wr_port:; } - log(" FIXME: The core of memory_bram is not implemented yet.\n"); + int grow_read_ports_cursor = -1; + bool try_growing_more_read_ports = false; + + if (0) { +grow_read_ports:; + rd_port_dups++; + mapped_rd_ports.clear(); + used_rd_ports.clear(); + } + + for (int cell_port_i = 0; cell_port_i < rd_ports; cell_port_i++) + { + bool clken = rd_clken[cell_port_i] == State::S1; + auto clkpol = rd_clkpol[cell_port_i] == State::S1; + auto clksig = rd_clk[cell_port_i]; + + pair clkdom(clksig, clkpol); + if (!clken) + clkdom = pair(State::S1, false); + + log(" Read port #%d is in clock domain %s%s.\n", + cell_port_i, clkdom.second ? "" : "!", + clken ? log_signal(clkdom.first) : "~async~"); + + for (int bram_port_i = 0; bram_port_i < GetSize(portinfos); bram_port_i++) + { + auto &pi = portinfos[bram_port_i]; + + if (pi.wrmode != 0 || used_rd_ports[bram_port_i] >= rd_port_dups) + skip_bram_rport: + continue; + + if (clken) { + if (pi.clocks == 0) { + log(" Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1); + goto skip_bram_rport; + } + if (clock_domains.count(pi.clocks) && clock_domains.at(pi.clocks) != clkdom) { + log(" Bram port %c%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1); + goto skip_bram_rport; + } + } else { + if (pi.clocks != 0) { + log(" Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1); + goto skip_bram_rport; + } + } + + log(" Mapped to bram port %c%d.%d.\n", pi.group + 'A', pi.index + 1, used_rd_ports[bram_port_i] + 1); + if (clken) + clock_domains[pi.clocks] = clkdom; + if (grow_read_ports_cursor < bram_port_i) { + grow_read_ports_cursor = bram_port_i; + try_growing_more_read_ports = true; + } + mapped_rd_ports.push_back(bram_port_i); + used_rd_ports[bram_port_i]++; + goto mapped_rd_port; + } + + log(" Failed to map read port #%d.\n", cell_port_i); + if (try_growing_more_read_ports) { + log(" Growing more read ports by duplicating bram cells.\n"); + goto grow_read_ports; + } + return false; + mapped_rd_port:; + } + + log(" FIXME: The core of memory_bram is not implemented yet.\n"); return false; } @@ -295,17 +385,17 @@ void handle_cell(Cell *cell, const rules_t &rules) { log("Processing %s.%s:\n", log_id(cell->module), log_id(cell)); - dict mem_properties; - mem_properties["words"] = cell->getParam("\\SIZE").as_int(); - mem_properties["abits"] = cell->getParam("\\ABITS").as_int(); - mem_properties["dbits"] = cell->getParam("\\WIDTH").as_int(); - mem_properties["wports"] = cell->getParam("\\WR_PORTS").as_int(); - mem_properties["rports"] = cell->getParam("\\RD_PORTS").as_int(); - mem_properties["bits"] = mem_properties["words"] * mem_properties["dbits"]; - mem_properties["ports"] = mem_properties["wports"] + mem_properties["rports"]; + dict match_properties; + match_properties["words"] = cell->getParam("\\SIZE").as_int(); + match_properties["abits"] = cell->getParam("\\ABITS").as_int(); + match_properties["dbits"] = cell->getParam("\\WIDTH").as_int(); + match_properties["wports"] = cell->getParam("\\WR_PORTS").as_int(); + match_properties["rports"] = cell->getParam("\\RD_PORTS").as_int(); + match_properties["bits"] = match_properties["words"] * match_properties["dbits"]; + match_properties["ports"] = match_properties["wports"] + match_properties["rports"]; log(" Properties:"); - for (auto &it : mem_properties) + for (auto &it : match_properties) log(" %s=%d", it.first.c_str(), it.second); log("\n"); @@ -313,37 +403,55 @@ void handle_cell(Cell *cell, const rules_t &rules) for (int i = 0; i < GetSize(rules.matches); i++) { - if (rules.matches[i].name.in(failed_brams)) - continue; - - for (auto it : rules.matches[i].min_limits) { - if (!mem_properties.count(it.first)) - log_error("Unknown property '%s' in match rule for bram type %s.\n", - it.first.c_str(), log_id(rules.matches[i].name)); - if (mem_properties[it.first] >= it.second) - continue; - log(" Rule #%d for bram type %s rejected: requirement 'min %s %d' not met.\n", - i, log_id(rules.matches[i].name), it.first.c_str(), it.second); - goto next_match_rule; - } - for (auto it : rules.matches[i].max_limits) { - if (!mem_properties.count(it.first)) - log_error("Unknown property '%s' in match rule for bram type %s.\n", - it.first.c_str(), log_id(rules.matches[i].name)); - if (mem_properties[it.first] <= it.second) - continue; - log(" Rule #%d for bram type %s rejected: requirement 'max %s %d' not met.\n", - i, log_id(rules.matches[i].name), it.first.c_str(), it.second); - goto next_match_rule; - } - - log(" Rule #%d for bram type %s accepted.\n", i, log_id(rules.matches[i].name)); if (!rules.brams.count(rules.matches[i].name)) log_error("No bram description for resource %s found!\n", log_id(rules.matches[i].name)); - if (!replace_cell(cell, rules.brams.at(rules.matches[i].name), rules.matches[i])) { - log(" Mapping to bram type %s failed.\n", log_id(rules.matches[i].name)); - failed_brams.insert(rules.matches[i].name); + auto &match = rules.matches.at(i); + auto &bram = rules.brams.at(match.name); + + if (match.name.in(failed_brams)) + continue; + + int aover = match_properties["words"] % (1 << bram.abits); + int awaste = aover ? (1 << bram.abits) - aover : 0; + match_properties["awaste"] = awaste; + + int dover = match_properties["dbits"] % bram.dbits; + int dwaste = dover ? bram.dbits - dover : 0; + match_properties["dwaste"] = dwaste; + + int waste = awaste * bram.dbits + dwaste * (1 << bram.abits) - awaste * dwaste; + match_properties["waste"] = waste; + + log(" Wasted bits for bram type %s: awaste=%d dwaste=%d waste=%d\n", + log_id(match.name), awaste, dwaste, waste); + + for (auto it : match.min_limits) { + if (!match_properties.count(it.first)) + log_error("Unknown property '%s' in match rule for bram type %s.\n", + it.first.c_str(), log_id(match.name)); + if (match_properties[it.first] >= it.second) + continue; + log(" Rule #%d for bram type %s rejected: requirement 'min %s %d' not met.\n", + i, log_id(match.name), it.first.c_str(), it.second); + goto next_match_rule; + } + for (auto it : match.max_limits) { + if (!match_properties.count(it.first)) + log_error("Unknown property '%s' in match rule for bram type %s.\n", + it.first.c_str(), log_id(match.name)); + if (match_properties[it.first] <= it.second) + continue; + log(" Rule #%d for bram type %s rejected: requirement 'max %s %d' not met.\n", + i, log_id(match.name), it.first.c_str(), it.second); + goto next_match_rule; + } + + log(" Rule #%d for bram type %s accepted.\n", i, log_id(match.name)); + + if (!replace_cell(cell, bram, match)) { + log(" Mapping to bram type %s failed.\n", log_id(match.name)); + failed_brams.insert(match.name); goto next_match_rule; } return; From eefe78be094f8009cdb4a7a0e657e86b9624adf1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 1 Jan 2015 12:56:01 +0100 Subject: [PATCH 245/492] Fixed memory->start_offset handling --- backends/ilang/ilang_backend.cc | 2 ++ frontends/ast/genrtlil.cc | 13 +++++++------ frontends/ilang/ilang_parser.y | 3 +++ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index dd5b6f3ce..60fb09901 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -150,6 +150,8 @@ void ILANG_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL f << stringf("width %d ", memory->width); if (memory->size != 0) f << stringf("size %d ", memory->size); + if (memory->start_offset != 0) + f << stringf("offset %d ", memory->start_offset); f << stringf("%s\n", memory->name.c_str()); } diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index a86d08d56..17d62d4dd 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -839,14 +839,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); memory->name = str; memory->width = children[0]->range_left - children[0]->range_right + 1; - memory->start_offset = children[0]->range_right; - memory->size = children[1]->range_left - children[1]->range_right; + if (children[1]->range_right < children[1]->range_left) { + memory->start_offset = children[1]->range_right; + memory->size = children[1]->range_left - children[1]->range_right + 1; + } else { + memory->start_offset = children[1]->range_left; + memory->size = children[1]->range_right - children[1]->range_left + 1; + } current_module->memories[memory->name] = memory; - if (memory->size < 0) - memory->size *= -1; - memory->size += std::min(children[1]->range_left, children[1]->range_right) + 1; - for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) log_error("Attribute `%s' with non-constant value at %s:%d!\n", diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y index 4e0981b51..4661d5772 100644 --- a/frontends/ilang/ilang_parser.y +++ b/frontends/ilang/ilang_parser.y @@ -183,6 +183,9 @@ memory_options: memory_options TOK_SIZE TOK_INT { current_memory->size = $3; } | + memory_options TOK_OFFSET TOK_INT { + current_memory->start_offset = $3; + } | /* empty */; cell_stmt: From f29f4e7c838b7c8bb965aca1c0acdcec8edfaa4a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 1 Jan 2015 15:32:37 +0100 Subject: [PATCH 246/492] Progress in memory_bram --- passes/memory/memory_bram.cc | 229 +++++++++++++++++++++++++++++++---- 1 file changed, 207 insertions(+), 22 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index ee6a35621..d33db1208 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -25,8 +25,12 @@ PRIVATE_NAMESPACE_BEGIN struct rules_t { struct portinfo_t { - int group, index; + int group, index, dupidx; int wrmode, enable, transp, clocks, clkpol; + + SigBit sig_clock; + SigSpec sig_addr, sig_data, sig_en; + int mapped_port; }; struct bram_t { @@ -42,11 +46,13 @@ struct rules_t portinfo_t pi; pi.group = i; pi.index = j; + pi.dupidx = 0; pi.wrmode = i < GetSize(wrmode) ? wrmode[i] : 0; pi.enable = i < GetSize(enable) ? enable[i] : 0; pi.transp = i < GetSize(transp) ? transp[i] : 0; pi.clocks = i < GetSize(clocks) ? clocks[i] : 0; pi.clkpol = i < GetSize(clkpol) ? clkpol[i] : 0; + pi.mapped_port = -1; portinfos.push_back(pi); } return portinfos; @@ -191,7 +197,7 @@ struct rules_t syntax_error(); } - void parse(std::string filename) + void parse(string filename) { infile.open(filename); linecount = 0; @@ -212,18 +218,27 @@ struct rules_t bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_t&) { + Module *module = cell->module; + auto portinfos = bram.make_portinfos(); + int dup_count = 1; + dict> clock_domains; - vector mapped_wr_ports, mapped_rd_ports; - dict used_rd_ports; - int rd_port_dups = 1; + pool clocks_wr_ports; + int clocks_max = 0; + + for (auto &pi : portinfos) { + if (pi.wrmode) + clocks_wr_ports.insert(pi.clocks); + clocks_max = std::max(clocks_max, pi.clocks); + } log(" Mapping to bram type %s:\n", log_id(bram.name)); int mem_size = cell->getParam("\\SIZE").as_int(); int mem_abits = cell->getParam("\\ABITS").as_int(); int mem_width = cell->getParam("\\WIDTH").as_int(); - int mem_offset = cell->getParam("\\OFFSET").as_int(); + // int mem_offset = cell->getParam("\\OFFSET").as_int(); int wr_ports = cell->getParam("\\WR_PORTS").as_int(); auto wr_clken = SigSpec(cell->getParam("\\WR_CLK_ENABLE")); @@ -286,10 +301,13 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ } } + SigSpec sig_en; SigBit last_en_bit = State::S1; - for (int i = 0; i < bram.dbits; i++) { - if (pi.enable && i % (bram.dbits / pi.enable) == 0) + for (int i = 0; i < mem_width; i++) { + if (pi.enable && i % (bram.dbits / pi.enable) == 0) { last_en_bit = wr_en[i]; + sig_en.append(last_en_bit); + } if (last_en_bit != wr_en[i]) { log(" Bram port %c%d has incompatible enable structure.\n", pi.group + 'A', pi.index + 1); goto skip_bram_wport; @@ -297,9 +315,17 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ } log(" Mapped to bram port %c%d.\n", pi.group + 'A', pi.index + 1); - if (clken) + pi.mapped_port = cell_port_i; + + if (clken) { clock_domains[pi.clocks] = clkdom; - mapped_wr_ports.push_back(bram_port_i); + pi.sig_clock = clkdom.first; + } + + pi.sig_en = sig_en; + pi.sig_addr = wr_addr.extract(cell_port_i*mem_abits, mem_abits); + pi.sig_data = wr_data.extract(cell_port_i*mem_width, mem_width); + goto mapped_wr_port; } @@ -313,9 +339,26 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ if (0) { grow_read_ports:; - rd_port_dups++; - mapped_rd_ports.clear(); - used_rd_ports.clear(); + vector new_portinfos; + for (auto &pi : portinfos) { + if (pi.wrmode == 0) { + pi.mapped_port = -1; + pi.sig_clock = SigBit(); + pi.sig_addr = SigSpec(); + pi.sig_data = SigSpec(); + pi.sig_en = SigSpec(); + } + new_portinfos.push_back(pi); + if (pi.dupidx == dup_count-1) { + if (pi.clocks && !clocks_wr_ports[pi.clocks]) + pi.clocks += clocks_max; + pi.dupidx++; + new_portinfos.push_back(pi); + } + } + try_growing_more_read_ports = false; + portinfos.swap(new_portinfos); + dup_count++; } for (int cell_port_i = 0; cell_port_i < rd_ports; cell_port_i++) @@ -336,7 +379,7 @@ grow_read_ports:; { auto &pi = portinfos[bram_port_i]; - if (pi.wrmode != 0 || used_rd_ports[bram_port_i] >= rd_port_dups) + if (pi.wrmode != 0 || pi.mapped_port >= 0) skip_bram_rport: continue; @@ -356,15 +399,21 @@ grow_read_ports:; } } - log(" Mapped to bram port %c%d.%d.\n", pi.group + 'A', pi.index + 1, used_rd_ports[bram_port_i] + 1); - if (clken) + log(" Mapped to bram port %c%d.%d.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + pi.mapped_port = cell_port_i; + + if (clken) { clock_domains[pi.clocks] = clkdom; - if (grow_read_ports_cursor < bram_port_i) { - grow_read_ports_cursor = bram_port_i; + pi.sig_clock = clkdom.first; + } + + pi.sig_addr = rd_addr.extract(cell_port_i*mem_abits, mem_abits); + pi.sig_data = rd_data.extract(cell_port_i*mem_width, mem_width); + + if (grow_read_ports_cursor < cell_port_i) { + grow_read_ports_cursor = cell_port_i; try_growing_more_read_ports = true; } - mapped_rd_ports.push_back(bram_port_i); - used_rd_ports[bram_port_i]++; goto mapped_rd_port; } @@ -377,8 +426,92 @@ grow_read_ports:; mapped_rd_port:; } - log(" FIXME: The core of memory_bram is not implemented yet.\n"); - return false; + dict> dout_cache; + + for (int grid_d = 0; grid_d*bram.dbits < mem_width; grid_d++) + for (int grid_a = 0; grid_a*(1 << bram.abits) < mem_size; grid_a++) + for (int dupidx = 0; dupidx < dup_count; dupidx++) + { + Cell *c = module->addCell(module->uniquify(stringf("%s.%d.%d.%d", cell->name.c_str(), grid_d, grid_a, dupidx)), bram.name); + log(" Creating %s cell at grid position <%d %d %d>: %s\n", log_id(bram.name), grid_d, grid_a, dupidx, log_id(c)); + + dict clocks; + + for (auto &pi : portinfos) + { + if (pi.dupidx != dupidx) + continue; + + string prefix = stringf("%c%d", pi.group + 'A', pi.index + 1); + const char *pf = prefix.c_str(); + + if (pi.clocks) + clocks[pi.clocks] = pi.sig_clock; + + SigSpec addr_ok; + if (GetSize(pi.sig_addr) > bram.abits) { + SigSpec extra_addr = pi.sig_addr.extract(bram.abits, GetSize(pi.sig_addr) - bram.abits); + SigSpec extra_addr_sel = SigSpec(grid_a, GetSize(extra_addr)); + addr_ok = module->Eq(NEW_ID, extra_addr, extra_addr_sel); + } + + if (pi.enable) + { + SigSpec sig_en = pi.sig_en; + sig_en.extend_u0((grid_d+1) * pi.enable); + sig_en = sig_en.extract(grid_d * pi.enable, pi.enable); + + if (!addr_ok.empty()) + sig_en = module->Mux(NEW_ID, SigSpec(0, GetSize(sig_en)), sig_en, addr_ok); + + c->setPort(stringf("\\%sEN", pf), sig_en); + } + + SigSpec sig_data = pi.sig_data; + sig_data.extend_u0((grid_d+1) * bram.dbits); + sig_data = sig_data.extract(grid_d * bram.dbits, bram.dbits); + + if (pi.wrmode == 1) { + c->setPort(stringf("\\%sDATA", pf), sig_data); + } else { + SigSpec bram_dout = module->addWire(NEW_ID, bram.dbits); + c->setPort(stringf("\\%sDATA", pf), bram_dout); + + for (int i = bram.dbits-1; i >= 0; i--) + if (sig_data[i].wire == nullptr) { + sig_data.remove(i); + bram_dout.remove(i); + } + + dout_cache[sig_data].first.append(addr_ok); + dout_cache[sig_data].second.append(bram_dout); + } + + SigSpec sig_addr = pi.sig_addr; + sig_addr.extend_u0(bram.abits); + c->setPort(stringf("\\%sADDR", pf), sig_addr); + } + + for (auto &it : clocks) + c->setPort(stringf("\\CLK%d", (it.first-1) % clocks_max + 1), it.second); + } + + for (auto &it : dout_cache) + { + if (it.second.first.empty()) + { + log_assert(GetSize(it.first) == GetSize(it.second.second)); + module->connect(it.first, it.second.second); + } + else + { + log_assert(GetSize(it.first)*GetSize(it.second.first) == GetSize(it.second.second)); + module->addPmux(NEW_ID, SigSpec(State::Sx, GetSize(it.first)), it.second.second, it.second.first, it.first); + } + } + + module->remove(cell); + return true; } void handle_cell(Cell *cell, const rules_t &rules) @@ -474,6 +607,58 @@ struct MemoryBramPass : public Pass { log("The given rules file describes the available resources and how they should be\n"); log("used.\n"); log("\n"); + log("The rules file contains a set of block ram description and a sequence of match\n"); + log("rules. A block ram description looks like this:\n"); + log("\n"); + log(" bram RAMB1024X32 # name of BRAM cell\n"); + log(" init 1 # set to '1' if BRAM can be initialized\n"); + log(" abits 10 # number of address bits\n"); + log(" dbits 32 # number of data bits\n"); + log(" groups 2 # number of port groups\n"); + log(" ports 1 1 # number of ports in each group\n"); + log(" wrmode 1 0 # set to '1' if this groups is write ports\n"); + log(" enable 4 0 # number of enable bits (for write ports)\n"); + log(" transp 0 2 # transparatent (for read ports)\n"); + log(" clocks 1 2 # clock configuration\n"); + log(" clkpol 2 2 # clock polarity configuration\n"); + log(" endbram\n"); + log("\n"); + log("For the option 'transp' the value 0 means non-transparent, 1 means transparent\n"); + log("and a value greater than 1 means configurable. All groups with the same\n"); + log("value greater than 1 share the same configuration bit.\n"); + log("\n"); + log("For the option 'clocks' the value 0 means non-clocked, and a value greater\n"); + log("than 0 means clocked. All groups with the same value share the same clock\n"); + log("signal.\n"); + log("\n"); + log("For the option 'clkpol' the value 0 means negative edge, 1 means positive edge\n"); + log("and a value greater than 1 means configurable. All groups with the same value\n"); + log("greater than 1 share the same configuration bit.\n"); + log("\n"); + log("A match rule looks like this:\n"); + log("\n"); + log(" match RAMB1024X32\n"); + log(" max waste 16384 # only use this if <= 16384 bram bits are unused\n"); + log(" endmatch\n"); + log("\n"); + log("It is possible to match against the following values with min/max rules:\n"); + log("\n"); + log(" words .... number of words in memory in design\n"); + log(" abits .... number of adress bits on memory in design\n"); + log(" dbits .... number of data bits on memory in design\n"); + log(" wports ... number of write ports on memory in design\n"); + log(" rports ... number of read ports on memory in design\n"); + log(" ports .... number of ports on memory in design\n"); + log(" bits ..... number of bits in memory in design\n"); + log("\n"); + log(" awaste ... number of unused address slots for this match\n"); + log(" dwaste ... number of unused data bits for this match\n"); + log(" waste .... total number of unused bram bits for this match\n"); + log("\n"); + log("The interface for the created bram instances is dervived from the bram\n"); + log("description. Use 'techmap' to convert the created bram instances into\n"); + log("instances of the actual bram cells of your target architecture.\n"); + log("\n"); } virtual void execute(vector args, Design *design) { From 340e7696670a4a7f46b01f2414945e6c4cefb1ce Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 1 Jan 2015 17:01:17 +0100 Subject: [PATCH 247/492] Bram testbench (incomplete) --- tests/bram/.gitignore | 1 + tests/bram/generate.py | 119 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 tests/bram/.gitignore create mode 100644 tests/bram/generate.py diff --git a/tests/bram/.gitignore b/tests/bram/.gitignore new file mode 100644 index 000000000..9c595a6fb --- /dev/null +++ b/tests/bram/.gitignore @@ -0,0 +1 @@ +temp diff --git a/tests/bram/generate.py b/tests/bram/generate.py new file mode 100644 index 000000000..f33bc8e03 --- /dev/null +++ b/tests/bram/generate.py @@ -0,0 +1,119 @@ +#!/usr/bin/python + +from __future__ import division +from __future__ import print_function + +import sys +import random + +def create_bram(dsc_f, sim_f, k1, k2): + while True: + init = random.randrange(2) + abits = random.randrange(1, 16) + dbits = random.randrange(1, 16) + groups = random.randrange(5) + + if random.randrange(2): + abits = 2 ** random.randrange(1, 4) + if random.randrange(2): + dbits = 2 ** random.randrange(1, 4) + + ports = [ random.randrange(3) for i in range(groups) ] + wrmode = [ random.randrange(2) for i in range(groups) ] + enable = [ random.randrange(4) for i in range(groups) ] + transp = [ random.randrange(4) for i in range(groups) ] + clocks = [ random.randrange(4) for i in range(groups) ] + clkpol = [ random.randrange(4) for i in range(groups) ] + + for p1 in range(groups): + if wrmode[p1] == 0: + enable[p1] = 0 + else: + enable[p1] = 2**enable[p1] + while dbits < enable[p1] or dbits % enable[p1] != 0: + enable[p1] //= 2 + + config_ok = True + if wrmode.count(1) <= ports.count(0): config_ok = False + if wrmode.count(0) <= ports.count(0): config_ok = False + if config_ok: break + + print('bram bram_%03d_%03d' % (k1, k2), file=dsc_f) + print(' init %d' % init, file=dsc_f) + print(' abits %d' % abits, file=dsc_f) + print(' dbits %d' % dbits, file=dsc_f) + print(' groups %d' % groups, file=dsc_f) + print(' ports %s' % " ".join(["%d" % i for i in ports]), file=dsc_f) + print(' wrmode %s' % " ".join(["%d" % i for i in wrmode]), file=dsc_f) + print(' enable %s' % " ".join(["%d" % i for i in enable]), file=dsc_f) + print(' transp %s' % " ".join(["%d" % i for i in transp]), file=dsc_f) + print(' clocks %s' % " ".join(["%d" % i for i in clocks]), file=dsc_f) + print(' clkpol %s' % " ".join(["%d" % i for i in clkpol]), file=dsc_f) + print('endbram', file=dsc_f) + print('match bram_%03d_%03d' % (k1, k2), file=dsc_f) + print('endmatch', file=dsc_f) + + states = set() + v_ports = set() + v_stmts = list() + + v_stmts.append("reg [%d:0] memory [0:%d];" % (dbits-1, 2**abits-1)) + + for p1 in range(groups): + for p2 in range(ports[p1]): + pf = "%c%d" % (chr(ord('A') + p1), p2 + 1) + + if clocks[p1] and not ("CLK%d" % clocks[p1]) in v_ports: + v_ports.add("CLK%d" % clocks[p1]) + v_stmts.append("input CLK%d;" % clocks[p1]) + + v_ports.add("%sADDR" % pf) + v_stmts.append("input [%d:0] %sADDR;" % (abits-1, pf)) + + v_ports.add("%sDATA" % pf) + v_stmts.append("%s [%d:0] %sDATA;" % ("input" if wrmode[p1] else "output reg", dbits-1, pf)) + + if wrmode[p1] and enable[p1]: + v_ports.add("%sEN" % pf) + v_stmts.append("input [%d:0] %sEN;" % (enable[p1]-1, pf)) + + assign_op = "<=" + if clocks[p1] == 0: + v_stmts.append("always @* begin") + assign_op = "=" + elif clkpol[p1] == 0: + v_stmts.append("always @(negedge CLK%d) begin" % clocks[p1]) + elif clkpol[p1] == 1: + v_stmts.append("always @(posedge CLK%d) begin" % clocks[p1]) + else: + if not ('CP', clkpol[p1]) in states: + v_stmts.append("parameter CLKPOL%d = 0;" % clkpol[p1]) + states.add(('CP', clkpol[p1])) + if not ('CPW', clocks[p1], clkpol[p1]) in states: + v_stmts.append("wire CLK%d_CLKPOL%d = CLK%d == CLKPOL%d;" % (clocks[p1], clkpol[p1], clocks[p1], clkpol[p1])) + states.add(('CPW', clocks[p1], clkpol[p1])) + v_stmts.append("always @(posedge CLK%d_CLKPOL%d) begin" % (clocks[p1], clkpol[p1])) + + if wrmode[p1]: + for i in range(enable[p1]): + enrange = "[%d:%d]" % ((i+1)*dbits/enable[p1]-1, i*dbits/enable[p1]) + v_stmts.append(" if (%sEN[%d]) memory[%sADDR]%s %s %sDATA%s;" % (pf, i, pf, enrange, assign_op, pf, enrange)) + else: + v_stmts.append(" %sDATA %s memory[%sADDR];" % (pf, assign_op, pf)) + v_stmts.append("end") + + print('module bram_%03d_%03d(%s);' % (k1, k2, ", ".join(v_ports)), file=sim_f) + for stmt in v_stmts: + print(' %s' % stmt, file=sim_f) + print('endmodule', file=sim_f) + +for k1 in range(10): + dsc_f = file('temp/brams_%03d.txt' % k1, 'w'); + sim_f = file('temp/brams_%03d.v' % k1, 'w'); + + for k2 in range(10): + create_bram(dsc_f, sim_f, k1, k2) + + dsc_f.close() + sim_f.close() + From 24ae156a747d5b933693878e7f2ed4c311e36570 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 1 Jan 2015 19:42:39 +0100 Subject: [PATCH 248/492] Progress in bram testbench --- tests/bram/generate.py | 181 ++++++++++++++++++++++++++++++--------- tests/bram/run-single.sh | 9 ++ tests/bram/run-test.sh | 32 +++++++ 3 files changed, 182 insertions(+), 40 deletions(-) create mode 100644 tests/bram/run-single.sh create mode 100755 tests/bram/run-test.sh diff --git a/tests/bram/generate.py b/tests/bram/generate.py index f33bc8e03..93255556d 100644 --- a/tests/bram/generate.py +++ b/tests/bram/generate.py @@ -6,11 +6,13 @@ from __future__ import print_function import sys import random -def create_bram(dsc_f, sim_f, k1, k2): +debug_mode = False + +def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): while True: init = random.randrange(2) - abits = random.randrange(1, 16) - dbits = random.randrange(1, 16) + abits = random.randrange(1, 8) + dbits = random.randrange(1, 8) groups = random.randrange(5) if random.randrange(2): @@ -25,6 +27,12 @@ def create_bram(dsc_f, sim_f, k1, k2): clocks = [ random.randrange(4) for i in range(groups) ] clkpol = [ random.randrange(4) for i in range(groups) ] + # XXX + init = 0 + transp = [ 0 for i in range(groups) ] + clocks = [ random.randrange(1, 4) for i in range(groups) ] + clkpol = [ 1 for i in range(groups) ] + for p1 in range(groups): if wrmode[p1] == 0: enable[p1] = 0 @@ -38,82 +46,175 @@ def create_bram(dsc_f, sim_f, k1, k2): if wrmode.count(0) <= ports.count(0): config_ok = False if config_ok: break - print('bram bram_%03d_%03d' % (k1, k2), file=dsc_f) - print(' init %d' % init, file=dsc_f) - print(' abits %d' % abits, file=dsc_f) - print(' dbits %d' % dbits, file=dsc_f) - print(' groups %d' % groups, file=dsc_f) - print(' ports %s' % " ".join(["%d" % i for i in ports]), file=dsc_f) - print(' wrmode %s' % " ".join(["%d" % i for i in wrmode]), file=dsc_f) - print(' enable %s' % " ".join(["%d" % i for i in enable]), file=dsc_f) - print(' transp %s' % " ".join(["%d" % i for i in transp]), file=dsc_f) - print(' clocks %s' % " ".join(["%d" % i for i in clocks]), file=dsc_f) - print(' clkpol %s' % " ".join(["%d" % i for i in clkpol]), file=dsc_f) - print('endbram', file=dsc_f) - print('match bram_%03d_%03d' % (k1, k2), file=dsc_f) - print('endmatch', file=dsc_f) + print("bram bram_%02d_%02d" % (k1, k2), file=dsc_f) + print(" init %d" % init, file=dsc_f) + print(" abits %d" % abits, file=dsc_f) + print(" dbits %d" % dbits, file=dsc_f) + print(" groups %d" % groups, file=dsc_f) + print(" ports %s" % " ".join(["%d" % i for i in ports]), file=dsc_f) + print(" wrmode %s" % " ".join(["%d" % i for i in wrmode]), file=dsc_f) + print(" enable %s" % " ".join(["%d" % i for i in enable]), file=dsc_f) + print(" transp %s" % " ".join(["%d" % i for i in transp]), file=dsc_f) + print(" clocks %s" % " ".join(["%d" % i for i in clocks]), file=dsc_f) + print(" clkpol %s" % " ".join(["%d" % i for i in clkpol]), file=dsc_f) + print("endbram", file=dsc_f) + print("match bram_%02d_%02d" % (k1, k2), file=dsc_f) + print("endmatch", file=dsc_f) states = set() v_ports = set() v_stmts = list() + v_always = dict() - v_stmts.append("reg [%d:0] memory [0:%d];" % (dbits-1, 2**abits-1)) + tb_decls = list() + tb_clocks = list() + tb_addr = list() + tb_din = list() + tb_dout = list() + tb_addrlist = list() + tb_delay = 0 + + for i in range(10): + tb_addrlist.append(random.randrange(1048576)) + + t = random.randrange(1048576) + for i in range(10): + tb_addrlist.append(t ^ (1 << i)) + + v_stmts.append("(* nomem2reg *) reg [%d:0] memory [0:%d];" % (dbits-1, 2**abits-1)) for p1 in range(groups): for p2 in range(ports[p1]): - pf = "%c%d" % (chr(ord('A') + p1), p2 + 1) + pf = "%c%d" % (chr(ord("A") + p1), p2 + 1) if clocks[p1] and not ("CLK%d" % clocks[p1]) in v_ports: v_ports.add("CLK%d" % clocks[p1]) v_stmts.append("input CLK%d;" % clocks[p1]) + tb_decls.append("reg CLK%d;" % clocks[p1]) + tb_clocks.append("CLK%d" % clocks[p1]) v_ports.add("%sADDR" % pf) v_stmts.append("input [%d:0] %sADDR;" % (abits-1, pf)) + tb_decls.append("reg [%d:0] %sADDR;" % (abits-1, pf)) + tb_addr.append("%sADDR" % pf) v_ports.add("%sDATA" % pf) v_stmts.append("%s [%d:0] %sDATA;" % ("input" if wrmode[p1] else "output reg", dbits-1, pf)) + if wrmode[p1]: + tb_decls.append("reg [%d:0] %sDATA;" % (dbits-1, pf)) + tb_din.append("%sDATA" % pf) + else: + tb_decls.append("wire [%d:0] %sDATA;" % (dbits-1, pf)) + tb_decls.append("wire [%d:0] %sDATA_R;" % (dbits-1, pf)) + tb_dout.append("%sDATA" % pf) + if wrmode[p1] and enable[p1]: v_ports.add("%sEN" % pf) v_stmts.append("input [%d:0] %sEN;" % (enable[p1]-1, pf)) + tb_decls.append("reg [%d:0] %sEN;" % (enable[p1]-1, pf)) + tb_din.append("%sEN" % pf) assign_op = "<=" if clocks[p1] == 0: - v_stmts.append("always @* begin") + always_hdr = "always @* begin" assign_op = "=" elif clkpol[p1] == 0: - v_stmts.append("always @(negedge CLK%d) begin" % clocks[p1]) + always_hdr = "always @(negedge CLK%d) begin" % clocks[p1] elif clkpol[p1] == 1: - v_stmts.append("always @(posedge CLK%d) begin" % clocks[p1]) + always_hdr = "always @(posedge CLK%d) begin" % clocks[p1] else: - if not ('CP', clkpol[p1]) in states: + if not ("CP", clkpol[p1]) in states: v_stmts.append("parameter CLKPOL%d = 0;" % clkpol[p1]) - states.add(('CP', clkpol[p1])) - if not ('CPW', clocks[p1], clkpol[p1]) in states: + states.add(("CP", clkpol[p1])) + if not ("CPW", clocks[p1], clkpol[p1]) in states: v_stmts.append("wire CLK%d_CLKPOL%d = CLK%d == CLKPOL%d;" % (clocks[p1], clkpol[p1], clocks[p1], clkpol[p1])) - states.add(('CPW', clocks[p1], clkpol[p1])) - v_stmts.append("always @(posedge CLK%d_CLKPOL%d) begin" % (clocks[p1], clkpol[p1])) + states.add(("CPW", clocks[p1], clkpol[p1])) + always_hdr = "always @(posedge CLK%d_CLKPOL%d) begin" % (clocks[p1], clkpol[p1]) + + if not always_hdr in v_always: + v_always[always_hdr] = list() if wrmode[p1]: + tb_delay += 1 + assign_op += " #%d" % tb_delay for i in range(enable[p1]): enrange = "[%d:%d]" % ((i+1)*dbits/enable[p1]-1, i*dbits/enable[p1]) - v_stmts.append(" if (%sEN[%d]) memory[%sADDR]%s %s %sDATA%s;" % (pf, i, pf, enrange, assign_op, pf, enrange)) + v_always[always_hdr].append("if (%sEN[%d]) memory[%sADDR]%s %s %sDATA%s;" % (pf, i, pf, enrange, assign_op, pf, enrange)) else: - v_stmts.append(" %sDATA %s memory[%sADDR];" % (pf, assign_op, pf)) - v_stmts.append("end") + v_always[always_hdr].append("%sDATA %s memory[%sADDR];" % (pf, assign_op, pf)) - print('module bram_%03d_%03d(%s);' % (k1, k2, ", ".join(v_ports)), file=sim_f) + for a in v_always: + v_stmts.append(a) + for l in v_always[a]: + v_stmts.append(" " + l) + v_stmts.append("end") + + print("module bram_%02d_%02d(%s);" % (k1, k2, ", ".join(v_ports)), file=sim_f) for stmt in v_stmts: - print(' %s' % stmt, file=sim_f) - print('endmodule', file=sim_f) + print(" %s" % stmt, file=sim_f) + print("endmodule", file=sim_f) -for k1 in range(10): - dsc_f = file('temp/brams_%03d.txt' % k1, 'w'); - sim_f = file('temp/brams_%03d.v' % k1, 'w'); + print("module bram_%02d_%02d_ref(%s);" % (k1, k2, ", ".join(v_ports)), file=ref_f) + for stmt in v_stmts: + print(" %s" % stmt, file=ref_f) + print("endmodule", file=ref_f) - for k2 in range(10): - create_bram(dsc_f, sim_f, k1, k2) + print("module bram_%02d_%02d_tb;" % (k1, k2), file=tb_f) + for stmt in tb_decls: + print(" %s" % stmt, file=tb_f) + print(" bram_%02d_%02d uut (" % (k1, k2), file=tb_f) + print(" " + ",\n ".join([".%s(%s)" % (p, p) for p in (tb_clocks + tb_addr + tb_din + tb_dout)]), file=tb_f) + print(" );", file=tb_f) + print(" bram_%02d_%02d_ref ref (" % (k1, k2), file=tb_f) + print(" " + ",\n ".join([".%s(%s)" % (p, p) for p in (tb_clocks + tb_addr + tb_din)]) + ",", file=tb_f) + print(" " + ",\n ".join([".%s(%s_R)" % (p, p) for p in tb_dout]), file=tb_f) + print(" );", file=tb_f) - dsc_f.close() - sim_f.close() + expr_dout = "{%s}" % ", ".join(tb_dout) + expr_dout_ref = "{%s}" % ", ".join(i + "_R" for i in tb_dout) + + print(" wire error = %s !== %s;" % (expr_dout, expr_dout_ref), file=tb_f) + + print(" initial begin", file=tb_f) + + if debug_mode: + print(" $dumpfile(\"temp/bram_%02d_%02d_tb.vcd\");" % (k1, k2), file=tb_f) + print(" $dumpvars(1, bram_%02d_%02d_tb);" % (k1, k2), file=tb_f) + + for p in (tb_clocks + tb_addr + tb_din): + if p[-2:] == "EN": + print(" %s <= ~0;" % p, file=tb_f) + else: + print(" %s <= 0;" % p, file=tb_f) + print(" #%d;" % (1000 + k2), file=tb_f) + + for v in [1, 0, 1, 0]: + for p in tb_clocks: + print(" %s = %d;" % (p, v), file=tb_f) + print(" #1000;", file=tb_f) + + for i in range(100): + for p in tb_din: + print(" %s = %d;" % (p, random.randrange(1048576)), file=tb_f) + for p in tb_addr: + print(" %s = %d;" % (p, random.choice(tb_addrlist)), file=tb_f) + if len(tb_clocks): + c = random.choice(tb_clocks) + print(" %s = !%s;" % (c, c), file=tb_f) + print(" #1;", file=tb_f) + print(" $display(\"bram_%02d_%02d %3d: %%b %%b %%s\", %s, %s, error ? \"ERROR\" : \"OK\");" % + (k1, k2, i, expr_dout, expr_dout_ref), file=tb_f) + + print(" end", file=tb_f) + print("endmodule", file=tb_f) + +for k1 in range(5): + dsc_f = file("temp/brams_%02d.txt" % k1, "w"); + sim_f = file("temp/brams_%02d.v" % k1, "w"); + ref_f = file("temp/brams_%02d_ref.v" % k1, "w"); + tb_f = file("temp/brams_%02d_tb.v" % k1, "w"); + + for k2 in range(1 if debug_mode else 10): + create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2) diff --git a/tests/bram/run-single.sh b/tests/bram/run-single.sh new file mode 100644 index 000000000..abaae0e2e --- /dev/null +++ b/tests/bram/run-single.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e +../../yosys -qq -p "proc; opt; memory -nomap; memory_bram -rules temp/brams_${2}.txt; opt -fast -full" \ + -l temp/synth_${1}_${2}.log -o temp/synth_${1}_${2}.v temp/brams_${1}.v +iverilog -o temp/tb_${1}_${2}.tb temp/brams_${1}_tb.v temp/brams_${1}_ref.v \ + temp/synth_${1}_${2}.v temp/brams_${2}.v ../../techlibs/common/simlib.v +temp/tb_${1}_${2}.tb > temp/tb_${1}_${2}.txt +if grep -H -C1 ERROR temp/tb_${1}_${2}.txt; then exit 1; fi +exit 0 diff --git a/tests/bram/run-test.sh b/tests/bram/run-test.sh new file mode 100755 index 000000000..cc18aff1e --- /dev/null +++ b/tests/bram/run-test.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# run this test many times: +# time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' + +set -e +rm -rf temp +mkdir -p temp + +echo "generating tests.." +python generate.py + +{ + echo -n "all:" + for i in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' ); do + for j in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' | grep -v $i ); do + echo -n " temp/job_$i$j.ok" + done; done + echo + for i in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' ); do + for j in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' | grep -v $i ); do + echo "temp/job_$i$j.ok:" + echo " @bash run-single.sh $i $j" + echo " @echo 'Passed test $i vs $j.'" + echo " @touch \$@" + done; done +} > temp/makefile + +echo "running tests.." +${MAKE:-make} -f temp/makefile + +exit 0 From 36c20f2ede51580f7c68b96b9cde9473187a8fc6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 2 Jan 2015 00:07:44 +0100 Subject: [PATCH 249/492] Progress in memory_bram --- passes/memory/memory_bram.cc | 11 ++++++++- tests/bram/generate.py | 44 ++++++++++++++++++++++-------------- tests/bram/run-single.sh | 2 +- tests/bram/run-test.sh | 8 +++---- 4 files changed, 42 insertions(+), 23 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index d33db1208..853950a34 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -30,6 +30,7 @@ struct rules_t SigBit sig_clock; SigSpec sig_addr, sig_data, sig_en; + bool effective_clkpol; int mapped_port; }; @@ -320,6 +321,7 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ if (clken) { clock_domains[pi.clocks] = clkdom; pi.sig_clock = clkdom.first; + pi.effective_clkpol = clkdom.second; } pi.sig_en = sig_en; @@ -405,6 +407,7 @@ grow_read_ports:; if (clken) { clock_domains[pi.clocks] = clkdom; pi.sig_clock = clkdom.first; + pi.effective_clkpol = clkdom.second; } pi.sig_addr = rd_addr.extract(cell_port_i*mem_abits, mem_abits); @@ -483,7 +486,13 @@ grow_read_ports:; bram_dout.remove(i); } - dout_cache[sig_data].first.append(addr_ok); + SigSpec addr_ok_q = addr_ok; + if (pi.clocks && !addr_ok.empty()) { + addr_ok_q = module->addWire(NEW_ID); + module->addDff(NEW_ID, pi.sig_clock, addr_ok, addr_ok_q, pi.effective_clkpol); + } + + dout_cache[sig_data].first.append(addr_ok_q); dout_cache[sig_data].second.append(bram_dout); } diff --git a/tests/bram/generate.py b/tests/bram/generate.py index 93255556d..37b23a526 100644 --- a/tests/bram/generate.py +++ b/tests/bram/generate.py @@ -13,7 +13,11 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): init = random.randrange(2) abits = random.randrange(1, 8) dbits = random.randrange(1, 8) - groups = random.randrange(5) + groups = random.randrange(1, 5) + + # XXX + init = 0 + groups = 2 if random.randrange(2): abits = 2 ** random.randrange(1, 4) @@ -28,10 +32,12 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): clkpol = [ random.randrange(4) for i in range(groups) ] # XXX - init = 0 + ports = [ 1 for i in range(groups) ] + wrmode = [ 1 for i in range(groups) ] transp = [ 0 for i in range(groups) ] - clocks = [ random.randrange(1, 4) for i in range(groups) ] + clocks = [ 1 for i in range(groups) ] clkpol = [ 1 for i in range(groups) ] + wrmode[0] = 0 for p1 in range(groups): if wrmode[p1] == 0: @@ -72,7 +78,6 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): tb_din = list() tb_dout = list() tb_addrlist = list() - tb_delay = 0 for i in range(10): tb_addrlist.append(random.randrange(1048576)) @@ -133,20 +138,22 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): always_hdr = "always @(posedge CLK%d_CLKPOL%d) begin" % (clocks[p1], clkpol[p1]) if not always_hdr in v_always: - v_always[always_hdr] = list() + v_always[always_hdr] = [list(), list(), list()] if wrmode[p1]: - tb_delay += 1 - assign_op += " #%d" % tb_delay for i in range(enable[p1]): enrange = "[%d:%d]" % ((i+1)*dbits/enable[p1]-1, i*dbits/enable[p1]) - v_always[always_hdr].append("if (%sEN[%d]) memory[%sADDR]%s %s %sDATA%s;" % (pf, i, pf, enrange, assign_op, pf, enrange)) + v_always[always_hdr][1].append("if (%sEN[%d]) memory[%sADDR]%s = %sDATA%s;" % (pf, i, pf, enrange, pf, enrange)) else: - v_always[always_hdr].append("%sDATA %s memory[%sADDR];" % (pf, assign_op, pf)) + v_always[always_hdr][2 if transp[p1] else 0].append("%sDATA %s memory[%sADDR];" % (pf, assign_op, pf)) for a in v_always: v_stmts.append(a) - for l in v_always[a]: + for l in v_always[a][0]: + v_stmts.append(" " + l) + for l in v_always[a][1]: + v_stmts.append(" " + l) + for l in v_always[a][2]: v_stmts.append(" " + l) v_stmts.append("end") @@ -179,8 +186,8 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): print(" initial begin", file=tb_f) if debug_mode: - print(" $dumpfile(\"temp/bram_%02d_%02d_tb.vcd\");" % (k1, k2), file=tb_f) - print(" $dumpvars(1, bram_%02d_%02d_tb);" % (k1, k2), file=tb_f) + print(" $dumpfile(`vcd_file);", file=tb_f) + print(" $dumpvars(2, bram_%02d_%02d_tb);" % (k1, k2), file=tb_f) for p in (tb_clocks + tb_addr + tb_din): if p[-2:] == "EN": @@ -195,14 +202,14 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): print(" #1000;", file=tb_f) for i in range(100): - for p in tb_din: - print(" %s = %d;" % (p, random.randrange(1048576)), file=tb_f) - for p in tb_addr: - print(" %s = %d;" % (p, random.choice(tb_addrlist)), file=tb_f) if len(tb_clocks): c = random.choice(tb_clocks) print(" %s = !%s;" % (c, c), file=tb_f) - print(" #1;", file=tb_f) + for p in tb_din: + print(" %s <= %d;" % (p, random.randrange(1048576)), file=tb_f) + for p in tb_addr: + print(" %s <= %d;" % (p, random.choice(tb_addrlist)), file=tb_f) + print(" #1000;", file=tb_f) print(" $display(\"bram_%02d_%02d %3d: %%b %%b %%s\", %s, %s, error ? \"ERROR\" : \"OK\");" % (k1, k2, i, expr_dout, expr_dout_ref), file=tb_f) @@ -215,6 +222,9 @@ for k1 in range(5): ref_f = file("temp/brams_%02d_ref.v" % k1, "w"); tb_f = file("temp/brams_%02d_tb.v" % k1, "w"); + for f in [sim_f, ref_f, tb_f]: + print("`timescale 1 ns / 1 ns", file=f) + for k2 in range(1 if debug_mode else 10): create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2) diff --git a/tests/bram/run-single.sh b/tests/bram/run-single.sh index abaae0e2e..254e85187 100644 --- a/tests/bram/run-single.sh +++ b/tests/bram/run-single.sh @@ -2,7 +2,7 @@ set -e ../../yosys -qq -p "proc; opt; memory -nomap; memory_bram -rules temp/brams_${2}.txt; opt -fast -full" \ -l temp/synth_${1}_${2}.log -o temp/synth_${1}_${2}.v temp/brams_${1}.v -iverilog -o temp/tb_${1}_${2}.tb temp/brams_${1}_tb.v temp/brams_${1}_ref.v \ +iverilog -Dvcd_file=\"temp/tb_${1}_${2}.vcd\" -o temp/tb_${1}_${2}.tb temp/brams_${1}_tb.v temp/brams_${1}_ref.v \ temp/synth_${1}_${2}.v temp/brams_${2}.v ../../techlibs/common/simlib.v temp/tb_${1}_${2}.tb > temp/tb_${1}_${2}.txt if grep -H -C1 ERROR temp/tb_${1}_${2}.txt; then exit 1; fi diff --git a/tests/bram/run-test.sh b/tests/bram/run-test.sh index cc18aff1e..68523740b 100755 --- a/tests/bram/run-test.sh +++ b/tests/bram/run-test.sh @@ -14,14 +14,14 @@ python generate.py echo -n "all:" for i in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' ); do for j in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' | grep -v $i ); do - echo -n " temp/job_$i$j.ok" + echo -n " temp/job_${i}_${j}.ok" done; done echo for i in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' ); do for j in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' | grep -v $i ); do - echo "temp/job_$i$j.ok:" - echo " @bash run-single.sh $i $j" - echo " @echo 'Passed test $i vs $j.'" + echo "temp/job_${i}_${j}.ok:" + echo " @bash run-single.sh ${i} ${j}" + echo " @echo 'Passed test ${i}_${j}.'" echo " @touch \$@" done; done } > temp/makefile From bbf89c4dc68475b57709897ab0728e31963a1ddb Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 2 Jan 2015 13:59:47 +0100 Subject: [PATCH 250/492] Progress in memory_bram --- Makefile | 1 + passes/memory/memory_bram.cc | 9 ++++++--- tests/bram/generate.py | 17 ++++++----------- tests/bram/run-single.sh | 5 ++++- tests/bram/run-test.sh | 2 +- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 73514e521..38e892131 100644 --- a/Makefile +++ b/Makefile @@ -264,6 +264,7 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/fsm && bash run-test.sh +cd tests/techmap && bash run-test.sh +cd tests/memories && bash run-test.sh + +cd tests/bram && bash run-test.sh +cd tests/various && bash run-test.sh +cd tests/sat && bash run-test.sh @echo "" diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 853950a34..1f7436d2d 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -306,10 +306,10 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ SigBit last_en_bit = State::S1; for (int i = 0; i < mem_width; i++) { if (pi.enable && i % (bram.dbits / pi.enable) == 0) { - last_en_bit = wr_en[i]; + last_en_bit = wr_en[i + cell_port_i*mem_width]; sig_en.append(last_en_bit); } - if (last_en_bit != wr_en[i]) { + if (last_en_bit != wr_en[i + cell_port_i*mem_width]) { log(" Bram port %c%d has incompatible enable structure.\n", pi.group + 'A', pi.index + 1); goto skip_bram_wport; } @@ -328,6 +328,7 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ pi.sig_addr = wr_addr.extract(cell_port_i*mem_abits, mem_abits); pi.sig_data = wr_data.extract(cell_port_i*mem_width, mem_width); + bram_port_i++; goto mapped_wr_port; } @@ -338,6 +339,7 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ int grow_read_ports_cursor = -1; bool try_growing_more_read_ports = false; + auto backup_clock_domains = clock_domains; if (0) { grow_read_ports:; @@ -360,6 +362,7 @@ grow_read_ports:; } try_growing_more_read_ports = false; portinfos.swap(new_portinfos); + clock_domains = backup_clock_domains; dup_count++; } @@ -448,7 +451,7 @@ grow_read_ports:; string prefix = stringf("%c%d", pi.group + 'A', pi.index + 1); const char *pf = prefix.c_str(); - if (pi.clocks) + if (pi.clocks && (!clocks.count(pi.clocks) || pi.sig_clock.wire)) clocks[pi.clocks] = pi.sig_clock; SigSpec addr_ok; diff --git a/tests/bram/generate.py b/tests/bram/generate.py index 37b23a526..b03d15296 100644 --- a/tests/bram/generate.py +++ b/tests/bram/generate.py @@ -15,10 +15,6 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): dbits = random.randrange(1, 8) groups = random.randrange(1, 5) - # XXX - init = 0 - groups = 2 - if random.randrange(2): abits = 2 ** random.randrange(1, 4) if random.randrange(2): @@ -32,12 +28,10 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): clkpol = [ random.randrange(4) for i in range(groups) ] # XXX - ports = [ 1 for i in range(groups) ] - wrmode = [ 1 for i in range(groups) ] + init = 0 transp = [ 0 for i in range(groups) ] clocks = [ 1 for i in range(groups) ] clkpol = [ 1 for i in range(groups) ] - wrmode[0] = 0 for p1 in range(groups): if wrmode[p1] == 0: @@ -187,7 +181,7 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): if debug_mode: print(" $dumpfile(`vcd_file);", file=tb_f) - print(" $dumpvars(2, bram_%02d_%02d_tb);" % (k1, k2), file=tb_f) + print(" $dumpvars(0, bram_%02d_%02d_tb);" % (k1, k2), file=tb_f) for p in (tb_clocks + tb_addr + tb_din): if p[-2:] == "EN": @@ -205,13 +199,14 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): if len(tb_clocks): c = random.choice(tb_clocks) print(" %s = !%s;" % (c, c), file=tb_f) + print(" #100;", file=tb_f) + print(" $display(\"bram_%02d_%02d %3d: %%b %%b %%s\", %s, %s, error ? \"ERROR\" : \"OK\");" % + (k1, k2, i, expr_dout, expr_dout_ref), file=tb_f) for p in tb_din: print(" %s <= %d;" % (p, random.randrange(1048576)), file=tb_f) for p in tb_addr: print(" %s <= %d;" % (p, random.choice(tb_addrlist)), file=tb_f) - print(" #1000;", file=tb_f) - print(" $display(\"bram_%02d_%02d %3d: %%b %%b %%s\", %s, %s, error ? \"ERROR\" : \"OK\");" % - (k1, k2, i, expr_dout, expr_dout_ref), file=tb_f) + print(" #900;", file=tb_f) print(" end", file=tb_f) print("endmodule", file=tb_f) diff --git a/tests/bram/run-single.sh b/tests/bram/run-single.sh index 254e85187..8a022e597 100644 --- a/tests/bram/run-single.sh +++ b/tests/bram/run-single.sh @@ -5,5 +5,8 @@ set -e iverilog -Dvcd_file=\"temp/tb_${1}_${2}.vcd\" -o temp/tb_${1}_${2}.tb temp/brams_${1}_tb.v temp/brams_${1}_ref.v \ temp/synth_${1}_${2}.v temp/brams_${2}.v ../../techlibs/common/simlib.v temp/tb_${1}_${2}.tb > temp/tb_${1}_${2}.txt -if grep -H -C1 ERROR temp/tb_${1}_${2}.txt; then exit 1; fi +if grep -q ERROR temp/tb_${1}_${2}.txt; then + grep -HC2 ERROR temp/tb_${1}_${2}.txt | head + exit 1 +fi exit 0 diff --git a/tests/bram/run-test.sh b/tests/bram/run-test.sh index 68523740b..cdf7d61b6 100755 --- a/tests/bram/run-test.sh +++ b/tests/bram/run-test.sh @@ -21,7 +21,7 @@ python generate.py for j in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' | grep -v $i ); do echo "temp/job_${i}_${j}.ok:" echo " @bash run-single.sh ${i} ${j}" - echo " @echo 'Passed test ${i}_${j}.'" + echo " @echo 'Passed memory_bram test ${i}_${j}.'" echo " @touch \$@" done; done } > temp/makefile From 474831643c9e75bd3930f566bc746bb4e330bce9 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 2 Jan 2015 17:11:31 +0100 Subject: [PATCH 251/492] New $mem simlib model --- techlibs/common/simlib.v | 131 +++++++++++---------------------------- 1 file changed, 36 insertions(+), 95 deletions(-) diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index bacf4a17e..ca4b1d36c 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1518,107 +1518,48 @@ input [WR_PORTS*WIDTH-1:0] WR_EN; input [WR_PORTS*ABITS-1:0] WR_ADDR; input [WR_PORTS*WIDTH-1:0] WR_DATA; -reg [WIDTH-1:0] data [SIZE-1:0]; -reg update_async_rd; +reg [WIDTH-1:0] memory [SIZE-1:0]; -genvar i; -generate +integer i, j; +reg [WR_PORTS-1:0] LAST_WR_CLK; +reg [RD_PORTS-1:0] LAST_RD_CLK; - for (i = 0; i < RD_PORTS; i = i+1) begin:rd - if (RD_CLK_ENABLE[i] == 0) begin:rd_noclk - always @(RD_ADDR or update_async_rd) - RD_DATA[i*WIDTH +: WIDTH] <= data[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; - end else - if (RD_TRANSPARENT[i] == 1) begin:rd_transparent - reg [ABITS-1:0] addr_buf; - if (RD_CLK_POLARITY[i] == 1) begin:rd_trans_posclk - always @(posedge RD_CLK[i]) - addr_buf <= RD_ADDR[i*ABITS +: ABITS]; - end else begin:rd_trans_negclk - always @(negedge RD_CLK[i]) - addr_buf <= RD_ADDR[i*ABITS +: ABITS]; - end - always @(addr_buf or update_async_rd) - RD_DATA[i*WIDTH +: WIDTH] <= data[addr_buf - OFFSET]; - end else begin:rd_notransparent - if (RD_CLK_POLARITY[i] == 1) begin:rd_notrans_posclk - always @(posedge RD_CLK[i]) - RD_DATA[i*WIDTH +: WIDTH] <= data[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; - end else begin:rd_notrans_negclk - always @(negedge RD_CLK[i]) - RD_DATA[i*WIDTH +: WIDTH] <= data[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; - end - end +function port_active; + input clk_enable; + input clk_polarity; + input last_clk; + input this_clk; + begin + casez ({clk_enable, clk_polarity, last_clk, this_clk}) + 4'b0???: port_active = 1; + 4'b1101: port_active = 1; + 4'b1010: port_active = 1; + default: port_active = 0; + endcase + end +endfunction + +always @* begin + for (i = 0; i < RD_PORTS; i = i+1) begin + if ((!RD_TRANSPARENT[i] && RD_CLK_ENABLE[i]) && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i])) + RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; end - for (i = 0; i < WR_PORTS; i = i+1) begin:wr - integer k, n; - reg found_collision, run_update; - if (WR_CLK_ENABLE[i] == 0) begin:wr_noclk - always @(WR_ADDR or WR_DATA or WR_EN) begin - run_update = 0; - for (n = 0; n < WIDTH; n = n+1) begin - if (WR_EN[i*WIDTH + n]) begin - found_collision = 0; - for (k = i+1; k < WR_PORTS; k = k+1) - if (WR_EN[k*WIDTH + n] && WR_ADDR[i*ABITS +: ABITS] == WR_ADDR[k*ABITS +: ABITS]) - found_collision = 1; - if (!found_collision) begin - data[WR_ADDR[i*ABITS +: ABITS] - OFFSET][n] <= WR_DATA[i*WIDTH + n]; - run_update = 1; - end - end - end - if (run_update) begin - update_async_rd <= 1; - update_async_rd <= 0; - end - end - end else - if (WR_CLK_POLARITY[i] == 1) begin:rd_posclk - always @(posedge WR_CLK[i]) begin - run_update = 0; - for (n = 0; n < WIDTH; n = n+1) begin - if (WR_EN[i*WIDTH + n]) begin - found_collision = 0; - for (k = i+1; k < WR_PORTS; k = k+1) - if (WR_EN[k*WIDTH + n] && WR_ADDR[i*ABITS +: ABITS] == WR_ADDR[k*ABITS +: ABITS]) - found_collision = 1; - if (!found_collision) begin - data[WR_ADDR[i*ABITS +: ABITS] - OFFSET][n] <= WR_DATA[i*WIDTH + n]; - run_update = 1; - end - end - end - if (run_update) begin - update_async_rd <= 1; - update_async_rd <= 0; - end - end - end else begin:rd_negclk - always @(negedge WR_CLK[i]) begin - run_update = 0; - for (n = 0; n < WIDTH; n = n+1) begin - if (WR_EN[i*WIDTH + n]) begin - found_collision = 0; - for (k = i+1; k < WR_PORTS; k = k+1) - if (WR_EN[k*WIDTH + n] && WR_ADDR[i*ABITS +: ABITS] == WR_ADDR[k*ABITS +: ABITS]) - found_collision = 1; - if (!found_collision) begin - data[WR_ADDR[i*ABITS +: ABITS] - OFFSET][n] <= WR_DATA[i*WIDTH + n]; - run_update = 1; - end - end - end - if (run_update) begin - update_async_rd <= 1; - update_async_rd <= 0; - end - end - end + for (i = 0; i < WR_PORTS; i = i+1) begin + if (port_active(WR_CLK_ENABLE[i], WR_CLK_POLARITY[i], LAST_WR_CLK[i], WR_CLK[i])) + for (j = 0; j < WIDTH; j = j+1) + if (WR_EN[i*WIDTH+j]) + memory[WR_ADDR[i*ABITS +: ABITS] - OFFSET][j] = WR_DATA[i*WIDTH+j]; end -endgenerate + for (i = 0; i < RD_PORTS; i = i+1) begin + if ((RD_TRANSPARENT[i] || !RD_CLK_ENABLE[i]) && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i])) + RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; + end + + LAST_RD_CLK <= RD_CLK; + LAST_WR_CLK <= WR_CLK; +end endmodule From 1bd67d792eefeb7e72bf74f80776b0d5e41d771a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 2 Jan 2015 17:11:54 +0100 Subject: [PATCH 252/492] Define YOSYS and SYNTHESIS in preproc --- frontends/verilog/preproc.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index b4e77c31b..4e5d16599 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -221,7 +221,8 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons input_buffer_charp = 0; input_file(f, filename); - defines_map["__YOSYS__"] = "1"; + defines_map["YOSYS"] = "1"; + defines_map["SYNTHESIS"] = "1"; while (!input_buffer.empty()) { From 03b3c025400b2e02afcdbb3337d16d82e361d6aa Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 2 Jan 2015 17:50:15 +0100 Subject: [PATCH 253/492] Progress in bram testbench --- tests/bram/generate.py | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/tests/bram/generate.py b/tests/bram/generate.py index b03d15296..b2419d7f4 100644 --- a/tests/bram/generate.py +++ b/tests/bram/generate.py @@ -3,34 +3,35 @@ from __future__ import division from __future__ import print_function +import os import sys import random debug_mode = False +seed = os.getpid() def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): while True: init = random.randrange(2) abits = random.randrange(1, 8) dbits = random.randrange(1, 8) - groups = random.randrange(1, 5) + groups = random.randrange(2, 5) if random.randrange(2): abits = 2 ** random.randrange(1, 4) if random.randrange(2): dbits = 2 ** random.randrange(1, 4) - ports = [ random.randrange(3) for i in range(groups) ] - wrmode = [ random.randrange(2) for i in range(groups) ] - enable = [ random.randrange(4) for i in range(groups) ] - transp = [ random.randrange(4) for i in range(groups) ] - clocks = [ random.randrange(4) for i in range(groups) ] - clkpol = [ random.randrange(4) for i in range(groups) ] + ports = [ random.randrange(1, 3) for i in range(groups) ] + wrmode = [ random.randrange(0, 2) for i in range(groups) ] + enable = [ random.randrange(0, 4) for i in range(groups) ] + transp = [ random.randrange(0, 4) for i in range(groups) ] + clocks = [ random.randrange(1, 4) for i in range(groups) ] + clkpol = [ random.randrange(0, 4) for i in range(groups) ] # XXX init = 0 transp = [ 0 for i in range(groups) ] - clocks = [ 1 for i in range(groups) ] clkpol = [ 1 for i in range(groups) ] for p1 in range(groups): @@ -42,8 +43,9 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): enable[p1] //= 2 config_ok = True - if wrmode.count(1) <= ports.count(0): config_ok = False - if wrmode.count(0) <= ports.count(0): config_ok = False + if sum(ports) > 3: config_ok = False # XXX + if wrmode.count(1) == 0: config_ok = False + if wrmode.count(0) == 0: config_ok = False if config_ok: break print("bram bram_%02d_%02d" % (k1, k2), file=dsc_f) @@ -82,9 +84,12 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): v_stmts.append("(* nomem2reg *) reg [%d:0] memory [0:%d];" % (dbits-1, 2**abits-1)) + portindex = 0 + for p1 in range(groups): for p2 in range(ports[p1]): pf = "%c%d" % (chr(ord("A") + p1), p2 + 1) + portindex += 1 if clocks[p1] and not ("CLK%d" % clocks[p1]) in v_ports: v_ports.add("CLK%d" % clocks[p1]) @@ -133,6 +138,8 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): if not always_hdr in v_always: v_always[always_hdr] = [list(), list(), list()] + v_always[always_hdr][1].append("`delay(%d)" % portindex); + v_always[always_hdr][2].append("`delay(%d)" % (sum(ports)-portindex+1)); if wrmode[p1]: for i in range(enable[p1]): @@ -195,7 +202,7 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): print(" %s = %d;" % (p, v), file=tb_f) print(" #1000;", file=tb_f) - for i in range(100): + for i in range(20 if debug_mode else 100): if len(tb_clocks): c = random.choice(tb_clocks) print(" %s = !%s;" % (c, c), file=tb_f) @@ -211,6 +218,9 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): print(" end", file=tb_f) print("endmodule", file=tb_f) +print("Rng seed: %d" % seed) +random.seed(seed) + for k1 in range(5): dsc_f = file("temp/brams_%02d.txt" % k1, "w"); sim_f = file("temp/brams_%02d.v" % k1, "w"); @@ -220,6 +230,13 @@ for k1 in range(5): for f in [sim_f, ref_f, tb_f]: print("`timescale 1 ns / 1 ns", file=f) + for f in [sim_f, ref_f]: + print("`ifdef SYNTHESIS", file=f) + print(" `define delay(n)", file=f) + print("`else", file=f) + print(" `define delay(n) #n;", file=f) + print("`endif", file=f) + for k2 in range(1 if debug_mode else 10): create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2) From 1dca7ae486edd47f786b07dba6a672b45ed9a4a5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 2 Jan 2015 18:54:22 +0100 Subject: [PATCH 254/492] Fixes and improvements in bram test --- tests/bram/generate.py | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/tests/bram/generate.py b/tests/bram/generate.py index b2419d7f4..514dfb9fb 100644 --- a/tests/bram/generate.py +++ b/tests/bram/generate.py @@ -8,7 +8,7 @@ import sys import random debug_mode = False -seed = os.getpid() +seed = (int(os.times()[4]*100) + os.getpid()) % 900000 + 100000 def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): while True: @@ -43,7 +43,6 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): enable[p1] //= 2 config_ok = True - if sum(ports) > 3: config_ok = False # XXX if wrmode.count(1) == 0: config_ok = False if wrmode.count(0) == 0: config_ok = False if config_ok: break @@ -66,7 +65,6 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): states = set() v_ports = set() v_stmts = list() - v_always = dict() tb_decls = list() tb_clocks = list() @@ -136,27 +134,17 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): states.add(("CPW", clocks[p1], clkpol[p1])) always_hdr = "always @(posedge CLK%d_CLKPOL%d) begin" % (clocks[p1], clkpol[p1]) - if not always_hdr in v_always: - v_always[always_hdr] = [list(), list(), list()] - v_always[always_hdr][1].append("`delay(%d)" % portindex); - v_always[always_hdr][2].append("`delay(%d)" % (sum(ports)-portindex+1)); - + v_stmts.append(always_hdr) if wrmode[p1]: + v_stmts.append(" `delay(%d)" % portindex); for i in range(enable[p1]): enrange = "[%d:%d]" % ((i+1)*dbits/enable[p1]-1, i*dbits/enable[p1]) - v_always[always_hdr][1].append("if (%sEN[%d]) memory[%sADDR]%s = %sDATA%s;" % (pf, i, pf, enrange, pf, enrange)) + v_stmts.append(" if (%sEN[%d]) memory[%sADDR]%s = %sDATA%s;" % (pf, i, pf, enrange, pf, enrange)) else: - v_always[always_hdr][2 if transp[p1] else 0].append("%sDATA %s memory[%sADDR];" % (pf, assign_op, pf)) - - for a in v_always: - v_stmts.append(a) - for l in v_always[a][0]: - v_stmts.append(" " + l) - for l in v_always[a][1]: - v_stmts.append(" " + l) - for l in v_always[a][2]: - v_stmts.append(" " + l) - v_stmts.append("end") + if transp[p1]: + v_stmts.append(" `delay(%d)" % (sum(ports)+1)) + v_stmts.append(" %sDATA %s memory[%sADDR];" % (pf, assign_op, pf)) + v_stmts.append("end") print("module bram_%02d_%02d(%s);" % (k1, k2, ", ".join(v_ports)), file=sim_f) for stmt in v_stmts: From 90f4017703a275c1a32cb347e4b60bd43873bbce Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 2 Jan 2015 22:45:26 +0100 Subject: [PATCH 255/492] Added proper clkpol support to memory_bram --- passes/memory/memory_bram.cc | 36 ++++++++++++++++++++++++++++++++---- techlibs/common/simlib.v | 2 +- tests/bram/generate.py | 2 +- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 1f7436d2d..356663e03 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -225,13 +225,23 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ int dup_count = 1; dict> clock_domains; + dict clock_polarities; pool clocks_wr_ports; + pool clkpol_wr_ports; int clocks_max = 0; + int clkpol_max = 0; + + clock_polarities[0] = false; + clock_polarities[1] = true; for (auto &pi : portinfos) { - if (pi.wrmode) + if (pi.wrmode) { clocks_wr_ports.insert(pi.clocks); + if (pi.clkpol > 1) + clkpol_wr_ports.insert(pi.clkpol); + } clocks_max = std::max(clocks_max, pi.clocks); + clkpol_max = std::max(clkpol_max, pi.clkpol); } log(" Mapping to bram type %s:\n", log_id(bram.name)); @@ -295,6 +305,10 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ log(" Bram port %c%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1); goto skip_bram_wport; } + if (clock_polarities.count(pi.clkpol) && clock_polarities.at(pi.clkpol) != clkpol) { + log(" Bram port %c%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1); + goto skip_bram_wport; + } } else { if (pi.clocks != 0) { log(" Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1); @@ -320,6 +334,7 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ if (clken) { clock_domains[pi.clocks] = clkdom; + clock_polarities[pi.clkpol] = clkdom.second; pi.sig_clock = clkdom.first; pi.effective_clkpol = clkdom.second; } @@ -340,6 +355,7 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ int grow_read_ports_cursor = -1; bool try_growing_more_read_ports = false; auto backup_clock_domains = clock_domains; + auto backup_clock_polarities = clock_polarities; if (0) { grow_read_ports:; @@ -356,6 +372,8 @@ grow_read_ports:; if (pi.dupidx == dup_count-1) { if (pi.clocks && !clocks_wr_ports[pi.clocks]) pi.clocks += clocks_max; + if (pi.clkpol > 1 && !clkpol_wr_ports[pi.clkpol]) + pi.clkpol += clkpol_max; pi.dupidx++; new_portinfos.push_back(pi); } @@ -363,6 +381,7 @@ grow_read_ports:; try_growing_more_read_ports = false; portinfos.swap(new_portinfos); clock_domains = backup_clock_domains; + clock_polarities = backup_clock_polarities; dup_count++; } @@ -390,16 +409,20 @@ grow_read_ports:; if (clken) { if (pi.clocks == 0) { - log(" Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1); + log(" Bram port %c%d.%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); goto skip_bram_rport; } if (clock_domains.count(pi.clocks) && clock_domains.at(pi.clocks) != clkdom) { - log(" Bram port %c%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1); + log(" Bram port %c%d.%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + goto skip_bram_rport; + } + if (clock_polarities.count(pi.clkpol) && clock_polarities.at(pi.clkpol) != clkpol) { + log(" Bram port %c%d.%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); goto skip_bram_rport; } } else { if (pi.clocks != 0) { - log(" Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1); + log(" Bram port %c%d.%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); goto skip_bram_rport; } } @@ -409,6 +432,7 @@ grow_read_ports:; if (clken) { clock_domains[pi.clocks] = clkdom; + clock_polarities[pi.clkpol] = clkdom.second; pi.sig_clock = clkdom.first; pi.effective_clkpol = clkdom.second; } @@ -506,6 +530,10 @@ grow_read_ports:; for (auto &it : clocks) c->setPort(stringf("\\CLK%d", (it.first-1) % clocks_max + 1), it.second); + + for (auto &it : clock_polarities) + if (it.first > 1) + c->setParam(stringf("\\CLKPOL%d", (it.first-1) % clkpol_max + 1), it.second); } for (auto &it : dout_cache) diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index ca4b1d36c..4680e209a 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1539,7 +1539,7 @@ function port_active; end endfunction -always @* begin +always @(RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA) begin for (i = 0; i < RD_PORTS; i = i+1) begin if ((!RD_TRANSPARENT[i] && RD_CLK_ENABLE[i]) && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i])) RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; diff --git a/tests/bram/generate.py b/tests/bram/generate.py index 514dfb9fb..0e803218a 100644 --- a/tests/bram/generate.py +++ b/tests/bram/generate.py @@ -32,7 +32,7 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): # XXX init = 0 transp = [ 0 for i in range(groups) ] - clkpol = [ 1 for i in range(groups) ] + clkpol = [ random.randrange(0, 2) for i in range(groups) ] for p1 in range(groups): if wrmode[p1] == 0: From 146f769beef2f6affa9df8e8265e0ca6519d3554 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 2 Jan 2015 22:46:20 +0100 Subject: [PATCH 256/492] Cosmetic changes in verilog output format --- backends/verilog/verilog_backend.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index be9479301..e9f4691b0 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -167,7 +167,7 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o if (data.bits[i] == RTLIL::S1) val |= 1 << (i - offset); } - f << stringf("32'%sd%d", set_signed ? "s" : "", val); + f << stringf("32'%sd %d", set_signed ? "s" : "", val); } else { dump_bits: f << stringf("%d'%sb", width, set_signed ? "s" : ""); @@ -246,14 +246,19 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig) } } -void dump_attributes(std::ostream &f, std::string indent, dict &attributes, char term = '\n') +void dump_attributes(std::ostream &f, std::string indent, dict &attributes, char term = '\n', bool modattr = false) { if (noattr) return; 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(" = "); - dump_const(f, it->second); + 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); f << stringf(" %s%c", attr2comment ? "*/" : "*)", term); } } @@ -749,7 +754,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) 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, !is_signed, is_signed); + dump_const(f, it->second, -1, 0, false, is_signed); f << stringf(")"); } f << stringf("\n%s" ")", indent.c_str()); @@ -991,7 +996,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) } } - dump_attributes(f, indent, module->attributes); + dump_attributes(f, indent, module->attributes, '\n', 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++) { From a7e43ae3d97ef14c8d624d8fdfe938ae9f47ce84 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 3 Jan 2015 10:57:01 +0100 Subject: [PATCH 257/492] Progress in memory_bram --- passes/memory/memory_bram.cc | 16 +++++----------- techlibs/common/simlib.v | 3 +++ tests/bram/generate.py | 25 ++++++++++++++----------- tests/bram/run-single.sh | 4 ++-- tests/bram/run-test.sh | 2 +- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 356663e03..0fb563bd0 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -465,8 +465,6 @@ grow_read_ports:; Cell *c = module->addCell(module->uniquify(stringf("%s.%d.%d.%d", cell->name.c_str(), grid_d, grid_a, dupidx)), bram.name); log(" Creating %s cell at grid position <%d %d %d>: %s\n", log_id(bram.name), grid_d, grid_a, dupidx, log_id(c)); - dict clocks; - for (auto &pi : portinfos) { if (pi.dupidx != dupidx) @@ -475,8 +473,11 @@ grow_read_ports:; string prefix = stringf("%c%d", pi.group + 'A', pi.index + 1); const char *pf = prefix.c_str(); - if (pi.clocks && (!clocks.count(pi.clocks) || pi.sig_clock.wire)) - clocks[pi.clocks] = pi.sig_clock; + if (pi.clocks && (!c->hasPort(stringf("\\CLK%d", (pi.clocks-1) % clocks_max + 1)) || pi.sig_clock.wire)) { + c->setPort(stringf("\\CLK%d", (pi.clocks-1) % clocks_max + 1), pi.sig_clock); + if (pi.clkpol > 1 && pi.sig_clock.wire) + c->setParam(stringf("\\CLKPOL%d", (pi.clkpol-1) % clkpol_max + 1), clock_polarities.at(pi.clkpol)); + } SigSpec addr_ok; if (GetSize(pi.sig_addr) > bram.abits) { @@ -527,13 +528,6 @@ grow_read_ports:; sig_addr.extend_u0(bram.abits); c->setPort(stringf("\\%sADDR", pf), sig_addr); } - - for (auto &it : clocks) - c->setPort(stringf("\\CLK%d", (it.first-1) % clocks_max + 1), it.second); - - for (auto &it : clock_polarities) - if (it.first > 1) - c->setParam(stringf("\\CLKPOL%d", (it.first-1) % clkpol_max + 1), it.second); } for (auto &it : dout_cache) diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 4680e209a..f16bd6bd2 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1540,6 +1540,9 @@ function port_active; endfunction always @(RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA) begin +`ifdef SIMLIB_MEMDELAY + #`SIMLIB_MEMDELAY; +`endif for (i = 0; i < RD_PORTS; i = i+1) begin if ((!RD_TRANSPARENT[i] && RD_CLK_ENABLE[i]) && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i])) RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; diff --git a/tests/bram/generate.py b/tests/bram/generate.py index 0e803218a..840bfbd98 100644 --- a/tests/bram/generate.py +++ b/tests/bram/generate.py @@ -32,7 +32,6 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): # XXX init = 0 transp = [ 0 for i in range(groups) ] - clkpol = [ random.randrange(0, 2) for i in range(groups) ] for p1 in range(groups): if wrmode[p1] == 0: @@ -134,15 +133,25 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): states.add(("CPW", clocks[p1], clkpol[p1])) always_hdr = "always @(posedge CLK%d_CLKPOL%d) begin" % (clocks[p1], clkpol[p1]) + v_stmts.append("`ifndef SYNTHESIS") + v_stmts.append("event UPDATE_%s;" % pf) + v_stmts.append("`endif") + v_stmts.append(always_hdr) if wrmode[p1]: - v_stmts.append(" `delay(%d)" % portindex); + v_stmts.append(" `ifndef SYNTHESIS"); + v_stmts.append(" #%d;" % portindex); + v_stmts.append(" -> UPDATE_%s;" % pf) + v_stmts.append(" `endif") for i in range(enable[p1]): enrange = "[%d:%d]" % ((i+1)*dbits/enable[p1]-1, i*dbits/enable[p1]) v_stmts.append(" if (%sEN[%d]) memory[%sADDR]%s = %sDATA%s;" % (pf, i, pf, enrange, pf, enrange)) else: + v_stmts.append(" `ifndef SYNTHESIS"); if transp[p1]: - v_stmts.append(" `delay(%d)" % (sum(ports)+1)) + v_stmts.append(" #%d;" % sum(ports)); + v_stmts.append(" -> UPDATE_%s;" % pf) + v_stmts.append(" `endif") v_stmts.append(" %sDATA %s memory[%sADDR];" % (pf, assign_op, pf)) v_stmts.append("end") @@ -177,13 +186,14 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): if debug_mode: print(" $dumpfile(`vcd_file);", file=tb_f) print(" $dumpvars(0, bram_%02d_%02d_tb);" % (k1, k2), file=tb_f) + print(" #%d;" % (1000 + k2), file=tb_f) for p in (tb_clocks + tb_addr + tb_din): if p[-2:] == "EN": print(" %s <= ~0;" % p, file=tb_f) else: print(" %s <= 0;" % p, file=tb_f) - print(" #%d;" % (1000 + k2), file=tb_f) + print(" #1000;", file=tb_f) for v in [1, 0, 1, 0]: for p in tb_clocks: @@ -218,13 +228,6 @@ for k1 in range(5): for f in [sim_f, ref_f, tb_f]: print("`timescale 1 ns / 1 ns", file=f) - for f in [sim_f, ref_f]: - print("`ifdef SYNTHESIS", file=f) - print(" `define delay(n)", file=f) - print("`else", file=f) - print(" `define delay(n) #n;", file=f) - print("`endif", file=f) - for k2 in range(1 if debug_mode else 10): create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2) diff --git a/tests/bram/run-single.sh b/tests/bram/run-single.sh index 8a022e597..cb8295d1b 100644 --- a/tests/bram/run-single.sh +++ b/tests/bram/run-single.sh @@ -2,8 +2,8 @@ set -e ../../yosys -qq -p "proc; opt; memory -nomap; memory_bram -rules temp/brams_${2}.txt; opt -fast -full" \ -l temp/synth_${1}_${2}.log -o temp/synth_${1}_${2}.v temp/brams_${1}.v -iverilog -Dvcd_file=\"temp/tb_${1}_${2}.vcd\" -o temp/tb_${1}_${2}.tb temp/brams_${1}_tb.v temp/brams_${1}_ref.v \ - temp/synth_${1}_${2}.v temp/brams_${2}.v ../../techlibs/common/simlib.v +iverilog -Dvcd_file=\"temp/tb_${1}_${2}.vcd\" -DSIMLIB_MEMDELAY=1ns -o temp/tb_${1}_${2}.tb temp/brams_${1}_tb.v \ + temp/brams_${1}_ref.v temp/synth_${1}_${2}.v temp/brams_${2}.v ../../techlibs/common/simlib.v temp/tb_${1}_${2}.tb > temp/tb_${1}_${2}.txt if grep -q ERROR temp/tb_${1}_${2}.txt; then grep -HC2 ERROR temp/tb_${1}_${2}.txt | head diff --git a/tests/bram/run-test.sh b/tests/bram/run-test.sh index cdf7d61b6..d617187ec 100755 --- a/tests/bram/run-test.sh +++ b/tests/bram/run-test.sh @@ -1,7 +1,7 @@ #!/bin/bash # run this test many times: -# time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' +# MAKE="make -j8" time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' set -e rm -rf temp From fd2c224c04b0fff83d2255c86533686fe2dc8883 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 3 Jan 2015 12:41:46 +0100 Subject: [PATCH 258/492] memory_bram transp support --- passes/memory/memory_bram.cc | 26 +++++++-- tests/bram/generate.py | 104 +++++++++++++++++++++-------------- 2 files changed, 86 insertions(+), 44 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 0fb563bd0..83a1d5b12 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -226,10 +226,12 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ dict> clock_domains; dict clock_polarities; + dict read_transp; pool clocks_wr_ports; pool clkpol_wr_ports; int clocks_max = 0; int clkpol_max = 0; + int transp_max = 0; clock_polarities[0] = false; clock_polarities[1] = true; @@ -242,6 +244,7 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ } clocks_max = std::max(clocks_max, pi.clocks); clkpol_max = std::max(clkpol_max, pi.clkpol); + transp_max = std::max(transp_max, pi.transp); } log(" Mapping to bram type %s:\n", log_id(bram.name)); @@ -277,8 +280,8 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ for (int cell_port_i = 0, bram_port_i = 0; cell_port_i < wr_ports; cell_port_i++) { bool clken = wr_clken[cell_port_i] == State::S1; - auto clkpol = wr_clkpol[cell_port_i] == State::S1; - auto clksig = wr_clk[cell_port_i]; + bool clkpol = wr_clkpol[cell_port_i] == State::S1; + SigBit clksig = wr_clk[cell_port_i]; pair clkdom(clksig, clkpol); if (!clken) @@ -374,6 +377,8 @@ grow_read_ports:; pi.clocks += clocks_max; if (pi.clkpol > 1 && !clkpol_wr_ports[pi.clkpol]) pi.clkpol += clkpol_max; + if (pi.transp > 1) + pi.transp += transp_max; pi.dupidx++; new_portinfos.push_back(pi); } @@ -385,11 +390,16 @@ grow_read_ports:; dup_count++; } + read_transp.clear(); + read_transp[0] = false; + read_transp[1] = true; + for (int cell_port_i = 0; cell_port_i < rd_ports; cell_port_i++) { bool clken = rd_clken[cell_port_i] == State::S1; - auto clkpol = rd_clkpol[cell_port_i] == State::S1; - auto clksig = rd_clk[cell_port_i]; + bool clkpol = rd_clkpol[cell_port_i] == State::S1; + bool transp = rd_transp[cell_port_i] == State::S1; + SigBit clksig = rd_clk[cell_port_i]; pair clkdom(clksig, clkpol); if (!clken) @@ -420,6 +430,10 @@ grow_read_ports:; log(" Bram port %c%d.%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); goto skip_bram_rport; } + if (read_transp.count(pi.transp) && read_transp.at(pi.transp) != transp) { + log(" Bram port %c%d.%d has incompatible read transparancy.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + goto skip_bram_rport; + } } else { if (pi.clocks != 0) { log(" Bram port %c%d.%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); @@ -433,6 +447,7 @@ grow_read_ports:; if (clken) { clock_domains[pi.clocks] = clkdom; clock_polarities[pi.clkpol] = clkdom.second; + read_transp[pi.transp] = transp; pi.sig_clock = clkdom.first; pi.effective_clkpol = clkdom.second; } @@ -444,6 +459,7 @@ grow_read_ports:; grow_read_ports_cursor = cell_port_i; try_growing_more_read_ports = true; } + goto mapped_rd_port; } @@ -477,6 +493,8 @@ grow_read_ports:; c->setPort(stringf("\\CLK%d", (pi.clocks-1) % clocks_max + 1), pi.sig_clock); if (pi.clkpol > 1 && pi.sig_clock.wire) c->setParam(stringf("\\CLKPOL%d", (pi.clkpol-1) % clkpol_max + 1), clock_polarities.at(pi.clkpol)); + if (pi.transp > 1 && pi.sig_clock.wire) + c->setParam(stringf("\\TRANSP%d", (pi.transp-1) % transp_max + 1), read_transp.at(pi.transp)); } SigSpec addr_ok; diff --git a/tests/bram/generate.py b/tests/bram/generate.py index 840bfbd98..7b5816fca 100644 --- a/tests/bram/generate.py +++ b/tests/bram/generate.py @@ -12,7 +12,7 @@ seed = (int(os.times()[4]*100) + os.getpid()) % 900000 + 100000 def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): while True: - init = random.randrange(2) + init = 0 # random.randrange(2) abits = random.randrange(1, 8) dbits = random.randrange(1, 8) groups = random.randrange(2, 5) @@ -22,29 +22,38 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): if random.randrange(2): dbits = 2 ** random.randrange(1, 4) - ports = [ random.randrange(1, 3) for i in range(groups) ] - wrmode = [ random.randrange(0, 2) for i in range(groups) ] - enable = [ random.randrange(0, 4) for i in range(groups) ] - transp = [ random.randrange(0, 4) for i in range(groups) ] - clocks = [ random.randrange(1, 4) for i in range(groups) ] - clkpol = [ random.randrange(0, 4) for i in range(groups) ] + while True: + wrmode = [ random.randrange(0, 2) for i in range(groups) ] + if wrmode.count(1) == 0: continue + if wrmode.count(0) == 0: continue + break - # XXX - init = 0 - transp = [ 0 for i in range(groups) ] + if random.randrange(2) or True: + maxpol = 4 + maxtransp = 1 + else: + maxpol = 2 + maxtransp = 2 - for p1 in range(groups): - if wrmode[p1] == 0: - enable[p1] = 0 - else: - enable[p1] = 2**enable[p1] - while dbits < enable[p1] or dbits % enable[p1] != 0: - enable[p1] //= 2 + def generate_enable(i): + if wrmode[i]: + v = 2 ** random.randrange(0, 4) + while dbits < v or dbits % v != 0: + v //= 2 + return v + return 0 - config_ok = True - if wrmode.count(1) == 0: config_ok = False - if wrmode.count(0) == 0: config_ok = False - if config_ok: break + def generate_transp(i): + if wrmode[i] == 0: + return random.randrange(maxtransp) + return 0 + + ports = [ random.randrange(1, 3) for i in range(groups) ] + enable = [ generate_enable(i) for i in range(groups) ] + transp = [ generate_transp(i) for i in range(groups) ] + clocks = [ random.randrange(1, 4) for i in range(groups) ] + clkpol = [ random.randrange(maxpol) for i in range(groups) ] + break print("bram bram_%02d_%02d" % (k1, k2), file=dsc_f) print(" init %d" % init, file=dsc_f) @@ -64,6 +73,7 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): states = set() v_ports = set() v_stmts = list() + v_always = dict() tb_decls = list() tb_clocks = list() @@ -82,12 +92,17 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): v_stmts.append("(* nomem2reg *) reg [%d:0] memory [0:%d];" % (dbits-1, 2**abits-1)) portindex = 0 + last_always_hdr = (-1, "") for p1 in range(groups): for p2 in range(ports[p1]): pf = "%c%d" % (chr(ord("A") + p1), p2 + 1) portindex += 1 + v_stmts.append("`ifndef SYNTHESIS") + v_stmts.append(" event UPDATE_%s;" % pf) + v_stmts.append("`endif") + if clocks[p1] and not ("CLK%d" % clocks[p1]) in v_ports: v_ports.add("CLK%d" % clocks[p1]) v_stmts.append("input CLK%d;" % clocks[p1]) @@ -133,27 +148,36 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): states.add(("CPW", clocks[p1], clkpol[p1])) always_hdr = "always @(posedge CLK%d_CLKPOL%d) begin" % (clocks[p1], clkpol[p1]) - v_stmts.append("`ifndef SYNTHESIS") - v_stmts.append("event UPDATE_%s;" % pf) - v_stmts.append("`endif") + if last_always_hdr[1] != always_hdr: + last_always_hdr = (portindex, always_hdr) + v_always[last_always_hdr] = list() - v_stmts.append(always_hdr) if wrmode[p1]: - v_stmts.append(" `ifndef SYNTHESIS"); - v_stmts.append(" #%d;" % portindex); - v_stmts.append(" -> UPDATE_%s;" % pf) - v_stmts.append(" `endif") for i in range(enable[p1]): enrange = "[%d:%d]" % ((i+1)*dbits/enable[p1]-1, i*dbits/enable[p1]) - v_stmts.append(" if (%sEN[%d]) memory[%sADDR]%s = %sDATA%s;" % (pf, i, pf, enrange, pf, enrange)) + v_always[last_always_hdr].append((portindex, pf, "if (%sEN[%d]) memory[%sADDR]%s = %sDATA%s;" % (pf, i, pf, enrange, pf, enrange))) else: - v_stmts.append(" `ifndef SYNTHESIS"); - if transp[p1]: - v_stmts.append(" #%d;" % sum(ports)); - v_stmts.append(" -> UPDATE_%s;" % pf) + v_always[last_always_hdr].append((sum(ports)+1 if transp[p1] else 0, pf, "%sDATA %s memory[%sADDR];" % (pf, assign_op, pf))) + + for always_hdr in sorted(v_always): + v_stmts.append(always_hdr[1]) + triggered_events = set() + time_cursor = 0 + v_always[always_hdr].sort() + for t, p, s in v_always[always_hdr]: + if time_cursor != t or not p in triggered_events: + v_stmts.append(" `ifndef SYNTHESIS") + stmt = "" + if time_cursor != t: + stmt += " #%d;" % (t-time_cursor) + time_cursor = t + if not p in triggered_events: + stmt += (" -> UPDATE_%s;" % p) + triggered_events.add(p) + v_stmts.append(" %s" % stmt) v_stmts.append(" `endif") - v_stmts.append(" %sDATA %s memory[%sADDR];" % (pf, assign_op, pf)) - v_stmts.append("end") + v_stmts.append(" %s" % s) + v_stmts.append("end") print("module bram_%02d_%02d(%s);" % (k1, k2, ", ".join(v_ports)), file=sim_f) for stmt in v_stmts: @@ -220,10 +244,10 @@ print("Rng seed: %d" % seed) random.seed(seed) for k1 in range(5): - dsc_f = file("temp/brams_%02d.txt" % k1, "w"); - sim_f = file("temp/brams_%02d.v" % k1, "w"); - ref_f = file("temp/brams_%02d_ref.v" % k1, "w"); - tb_f = file("temp/brams_%02d_tb.v" % k1, "w"); + dsc_f = file("temp/brams_%02d.txt" % k1, "w") + sim_f = file("temp/brams_%02d.v" % k1, "w") + ref_f = file("temp/brams_%02d_ref.v" % k1, "w") + tb_f = file("temp/brams_%02d_tb.v" % k1, "w") for f in [sim_f, ref_f, tb_f]: print("`timescale 1 ns / 1 ns", file=f) From a7fe87f8886900b3e9056caf392978e06c5a74ae Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 3 Jan 2015 17:34:05 +0100 Subject: [PATCH 259/492] Added memory_bram 'or_next_if_better' feature --- passes/memory/memory_bram.cc | 198 +++++++++++++++++++++++++++-------- tests/bram/generate.py | 9 +- 2 files changed, 162 insertions(+), 45 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 83a1d5b12..868289892 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -63,6 +63,7 @@ struct rules_t struct match_t { IdString name; dict min_limits, max_limits; + bool or_next_if_better; }; dict brams; @@ -174,6 +175,7 @@ struct rules_t match_t data; data.name = RTLIL::escape_id(tokens[1]); + data.or_next_if_better = false; while (next_line()) { @@ -192,6 +194,11 @@ struct rules_t continue; } + if (GetSize(tokens) == 1 && tokens[0] == "or_next_if_better") { + data.or_next_if_better = true; + continue; + } + break; } @@ -217,7 +224,7 @@ struct rules_t } }; -bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_t&) +bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_t &match, dict &match_properties, int mode) { Module *module = cell->module; @@ -247,7 +254,7 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ transp_max = std::max(transp_max, pi.transp); } - log(" Mapping to bram type %s:\n", log_id(bram.name)); + log(" Mapping to bram type %s:\n", log_id(bram.name)); int mem_size = cell->getParam("\\SIZE").as_int(); int mem_abits = cell->getParam("\\ABITS").as_int(); @@ -287,7 +294,7 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ if (!clken) clkdom = pair(State::S1, false); - log(" Write port #%d is in clock domain %s%s.\n", + log(" Write port #%d is in clock domain %s%s.\n", cell_port_i, clkdom.second ? "" : "!", clken ? log_signal(clkdom.first) : "~async~"); @@ -301,20 +308,20 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ if (clken) { if (pi.clocks == 0) { - log(" Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1); + log(" Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1); goto skip_bram_wport; } if (clock_domains.count(pi.clocks) && clock_domains.at(pi.clocks) != clkdom) { - log(" Bram port %c%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1); + log(" Bram port %c%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1); goto skip_bram_wport; } if (clock_polarities.count(pi.clkpol) && clock_polarities.at(pi.clkpol) != clkpol) { - log(" Bram port %c%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1); + log(" Bram port %c%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1); goto skip_bram_wport; } } else { if (pi.clocks != 0) { - log(" Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1); + log(" Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1); goto skip_bram_wport; } } @@ -327,12 +334,12 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ sig_en.append(last_en_bit); } if (last_en_bit != wr_en[i + cell_port_i*mem_width]) { - log(" Bram port %c%d has incompatible enable structure.\n", pi.group + 'A', pi.index + 1); + log(" Bram port %c%d has incompatible enable structure.\n", pi.group + 'A', pi.index + 1); goto skip_bram_wport; } } - log(" Mapped to bram port %c%d.\n", pi.group + 'A', pi.index + 1); + log(" Mapped to bram port %c%d.\n", pi.group + 'A', pi.index + 1); pi.mapped_port = cell_port_i; if (clken) { @@ -350,7 +357,7 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ goto mapped_wr_port; } - log(" Failed to map write port #%d.\n", cell_port_i); + log(" Failed to map write port #%d.\n", cell_port_i); return false; mapped_wr_port:; } @@ -405,7 +412,7 @@ grow_read_ports:; if (!clken) clkdom = pair(State::S1, false); - log(" Read port #%d is in clock domain %s%s.\n", + log(" Read port #%d is in clock domain %s%s.\n", cell_port_i, clkdom.second ? "" : "!", clken ? log_signal(clkdom.first) : "~async~"); @@ -419,29 +426,29 @@ grow_read_ports:; if (clken) { if (pi.clocks == 0) { - log(" Bram port %c%d.%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + log(" Bram port %c%d.%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); goto skip_bram_rport; } if (clock_domains.count(pi.clocks) && clock_domains.at(pi.clocks) != clkdom) { - log(" Bram port %c%d.%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + log(" Bram port %c%d.%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); goto skip_bram_rport; } if (clock_polarities.count(pi.clkpol) && clock_polarities.at(pi.clkpol) != clkpol) { - log(" Bram port %c%d.%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + log(" Bram port %c%d.%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); goto skip_bram_rport; } if (read_transp.count(pi.transp) && read_transp.at(pi.transp) != transp) { - log(" Bram port %c%d.%d has incompatible read transparancy.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + log(" Bram port %c%d.%d has incompatible read transparancy.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); goto skip_bram_rport; } } else { if (pi.clocks != 0) { - log(" Bram port %c%d.%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + log(" Bram port %c%d.%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); goto skip_bram_rport; } } - log(" Mapped to bram port %c%d.%d.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + log(" Mapped to bram port %c%d.%d.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); pi.mapped_port = cell_port_i; if (clken) { @@ -463,15 +470,51 @@ grow_read_ports:; goto mapped_rd_port; } - log(" Failed to map read port #%d.\n", cell_port_i); + log(" Failed to map read port #%d.\n", cell_port_i); if (try_growing_more_read_ports) { - log(" Growing more read ports by duplicating bram cells.\n"); + log(" Growing more read ports by duplicating bram cells.\n"); goto grow_read_ports; } return false; mapped_rd_port:; } + if (mode <= 1) + { + match_properties["dups"] = dup_count; + match_properties["waste"] = match_properties["dups"] * match_properties["bwaste"]; + + int cells = ((match_properties["dbits"] + bram.dbits - 1) / bram.dbits) * ((match_properties["words"] + (1 << bram.abits) - 1) / (1 << bram.abits)); + match_properties["efficiency"] = (100 * match_properties["bits"]) / (dup_count * cells * bram.dbits * (1 << bram.abits)); + + log(" Updated properties: dups=%d waste=%d efficiency=%d\n", + match_properties["dups"], match_properties["waste"], match_properties["efficiency"]); + + for (auto it : match.min_limits) { + if (!match_properties.count(it.first)) + log_error("Unknown property '%s' in match rule for bram type %s.\n", + it.first.c_str(), log_id(match.name)); + if (match_properties[it.first] >= it.second) + continue; + log(" Rule for bram type %s rejected: requirement 'min %s %d' not met.\n", + log_id(match.name), it.first.c_str(), it.second); + return false; + } + for (auto it : match.max_limits) { + if (!match_properties.count(it.first)) + log_error("Unknown property '%s' in match rule for bram type %s.\n", + it.first.c_str(), log_id(match.name)); + if (match_properties[it.first] <= it.second) + continue; + log(" Rule for bram type %s rejected: requirement 'max %s %d' not met.\n", + log_id(match.name), it.first.c_str(), it.second); + return false; + } + + if (mode == 1) + return true; + } + dict> dout_cache; for (int grid_d = 0; grid_d*bram.dbits < mem_width; grid_d++) @@ -479,7 +522,7 @@ grow_read_ports:; for (int dupidx = 0; dupidx < dup_count; dupidx++) { Cell *c = module->addCell(module->uniquify(stringf("%s.%d.%d.%d", cell->name.c_str(), grid_d, grid_a, dupidx)), bram.name); - log(" Creating %s cell at grid position <%d %d %d>: %s\n", log_id(bram.name), grid_d, grid_a, dupidx, log_id(c)); + log(" Creating %s cell at grid position <%d %d %d>: %s\n", log_id(bram.name), grid_d, grid_a, dupidx, log_id(c)); for (auto &pi : portinfos) { @@ -585,6 +628,7 @@ void handle_cell(Cell *cell, const rules_t &rules) log("\n"); pool failed_brams; + dict best_rule_cache; for (int i = 0; i < GetSize(rules.matches); i++) { @@ -597,6 +641,23 @@ void handle_cell(Cell *cell, const rules_t &rules) if (match.name.in(failed_brams)) continue; + int avail_rd_ports = 0; + int avail_wr_ports = 0; + for (int j = 0; j < bram.groups; j++) { + if (GetSize(bram.wrmode) < j || bram.wrmode.at(j) == 0) + avail_rd_ports += GetSize(bram.ports) < j ? bram.ports.at(j) : 0; + if (GetSize(bram.wrmode) < j || bram.wrmode.at(j) != 0) + avail_wr_ports += GetSize(bram.ports) < j ? bram.ports.at(j) : 0; + } + + log(" Checking rule #%d for bram type %s:\n", i, log_id(match.name)); + log(" Bram geometry: abits=%d dbits=%d wports=%d rports=%d\n", bram.abits, bram.dbits, avail_wr_ports, avail_rd_ports); + + int dups = avail_rd_ports ? (match_properties["rports"] + avail_rd_ports - 1) / avail_rd_ports : 1; + match_properties["dups"] = dups; + + log(" Estimated number of duplicates for more read ports: dups=%d\n", match_properties["dups"]); + int aover = match_properties["words"] % (1 << bram.abits); int awaste = aover ? (1 << bram.abits) - aover : 0; match_properties["awaste"] = awaste; @@ -605,19 +666,28 @@ void handle_cell(Cell *cell, const rules_t &rules) int dwaste = dover ? bram.dbits - dover : 0; match_properties["dwaste"] = dwaste; - int waste = awaste * bram.dbits + dwaste * (1 << bram.abits) - awaste * dwaste; + int bwaste = awaste * bram.dbits + dwaste * (1 << bram.abits) - awaste * dwaste; + match_properties["bwaste"] = bwaste; + + int waste = match_properties["dups"] * bwaste; match_properties["waste"] = waste; - log(" Wasted bits for bram type %s: awaste=%d dwaste=%d waste=%d\n", - log_id(match.name), awaste, dwaste, waste); + int cells = ((match_properties["dbits"] + bram.dbits - 1) / bram.dbits) * ((match_properties["words"] + (1 << bram.abits) - 1) / (1 << bram.abits)); + int efficiency = (100 * match_properties["bits"]) / (dups * cells * bram.dbits * (1 << bram.abits)); + match_properties["efficiency"] = efficiency; + + log(" Metrics for %s: awaste=%d dwaste=%d bwaste=%d waste=%d efficiency=%d %d\n", + log_id(match.name), awaste, dwaste, bwaste, waste, efficiency, cells); for (auto it : match.min_limits) { + if (it.first == "waste" || it.first == "dups") + continue; if (!match_properties.count(it.first)) log_error("Unknown property '%s' in match rule for bram type %s.\n", it.first.c_str(), log_id(match.name)); if (match_properties[it.first] >= it.second) continue; - log(" Rule #%d for bram type %s rejected: requirement 'min %s %d' not met.\n", + log(" Rule #%d for bram type %s rejected: requirement 'min %s %d' not met.\n", i, log_id(match.name), it.first.c_str(), it.second); goto next_match_rule; } @@ -627,21 +697,57 @@ void handle_cell(Cell *cell, const rules_t &rules) it.first.c_str(), log_id(match.name)); if (match_properties[it.first] <= it.second) continue; - log(" Rule #%d for bram type %s rejected: requirement 'max %s %d' not met.\n", + log(" Rule #%d for bram type %s rejected: requirement 'max %s %d' not met.\n", i, log_id(match.name), it.first.c_str(), it.second); goto next_match_rule; } - log(" Rule #%d for bram type %s accepted.\n", i, log_id(match.name)); + log(" Rule #%d for bram type %s accepted.\n", i, log_id(match.name)); - if (!replace_cell(cell, bram, match)) { - log(" Mapping to bram type %s failed.\n", log_id(match.name)); + if (match.or_next_if_better || !best_rule_cache.empty()) + { + if (match.or_next_if_better && i+1 == GetSize(rules.matches)) + log_error("Found 'or_next_if_better' in last match rule.\n"); + + if (!replace_cell(cell, bram, match, match_properties, 1)) { + log(" Mapping to bram type %s failed.\n", log_id(match.name)); + failed_brams.insert(match.name); + goto next_match_rule; + } + + log(" Storing for later selection.\n"); + best_rule_cache[i] = match_properties["efficiency"]; + + if (match.or_next_if_better) + goto next_match_rule; + + next_match_rule: + if (match.or_next_if_better || best_rule_cache.empty()) + continue; + + log(" Selecting best of %d rules:\n", GetSize(best_rule_cache)); + int best_rule = best_rule_cache.begin()->first; + + for (auto &it : best_rule_cache) { + if (it.second > best_rule_cache[best_rule]) + best_rule = it.first; + log(" Efficiency for rule %d: %d\n", it.first, it.second); + } + + log(" Selected rule %d with efficiency %d.\n", best_rule, best_rule_cache[best_rule]); + best_rule_cache.clear(); + + if (!replace_cell(cell, rules.brams.at(rules.matches.at(best_rule).name), rules.matches.at(best_rule), match_properties, 2)) + log_error("Mapping to bram type %s after pre-selection failed.\n", log_id(rules.matches.at(best_rule).name)); + return; + } + + if (!replace_cell(cell, bram, match, match_properties, 0)) { + log(" Mapping to bram type %s failed.\n", log_id(match.name)); failed_brams.insert(match.name); goto next_match_rule; } return; - - next_match_rule:; } log(" No acceptable bram resources found.\n"); @@ -663,7 +769,7 @@ struct MemoryBramPass : public Pass { log("rules. A block ram description looks like this:\n"); log("\n"); log(" bram RAMB1024X32 # name of BRAM cell\n"); - log(" init 1 # set to '1' if BRAM can be initialized\n"); + // log(" init 1 # set to '1' if BRAM can be initialized\n"); log(" abits 10 # number of address bits\n"); log(" dbits 32 # number of data bits\n"); log(" groups 2 # number of port groups\n"); @@ -690,27 +796,35 @@ struct MemoryBramPass : public Pass { log("A match rule looks like this:\n"); log("\n"); log(" match RAMB1024X32\n"); - log(" max waste 16384 # only use this if <= 16384 bram bits are unused\n"); + log(" max waste 16384 # only use this bram if <= 16k ram bits are unused\n"); + log(" min efficiency 80 # only use this bram if efficiency is at least 80%%\n"); log(" endmatch\n"); log("\n"); log("It is possible to match against the following values with min/max rules:\n"); log("\n"); - log(" words .... number of words in memory in design\n"); - log(" abits .... number of adress bits on memory in design\n"); - log(" dbits .... number of data bits on memory in design\n"); - log(" wports ... number of write ports on memory in design\n"); - log(" rports ... number of read ports on memory in design\n"); - log(" ports .... number of ports on memory in design\n"); - log(" bits ..... number of bits in memory in design\n"); + log(" words ........ number of words in memory in design\n"); + log(" abits ........ number of adress bits on memory in design\n"); + log(" dbits ........ number of data bits on memory in design\n"); + log(" wports ....... number of write ports on memory in design\n"); + log(" rports ....... number of read ports on memory in design\n"); + log(" ports ........ number of ports on memory in design\n"); + log(" bits ......... number of bits in memory in design\n"); + log(" dups .......... number of duplications for more read ports\n"); log("\n"); - log(" awaste ... number of unused address slots for this match\n"); - log(" dwaste ... number of unused data bits for this match\n"); - log(" waste .... total number of unused bram bits for this match\n"); + log(" awaste ....... number of unused address slots for this match\n"); + log(" dwaste ....... number of unused data bits for this match\n"); + log(" bwaste ....... number of unused bram bits for this match\n"); + log(" waste ........ total number of unused bram bits (bwaste*dups)\n"); + log(" efficiency ... total percentage of used and non-duplicated bits\n"); log("\n"); log("The interface for the created bram instances is dervived from the bram\n"); log("description. Use 'techmap' to convert the created bram instances into\n"); log("instances of the actual bram cells of your target architecture.\n"); log("\n"); + log("A match containing the command 'or_next_if_better' is only used if it\n"); + log("has a higher efficiency than the next match (and the one after that if\n"); + log("the next also has 'or_next_if_better' set, and so forth).\n"); + log("\n"); } virtual void execute(vector args, Design *design) { diff --git a/tests/bram/generate.py b/tests/bram/generate.py index 7b5816fca..03f2555dc 100644 --- a/tests/bram/generate.py +++ b/tests/bram/generate.py @@ -10,7 +10,7 @@ import random debug_mode = False seed = (int(os.times()[4]*100) + os.getpid()) % 900000 + 100000 -def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): +def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2, or_next): while True: init = 0 # random.randrange(2) abits = random.randrange(1, 8) @@ -68,6 +68,8 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2): print(" clkpol %s" % " ".join(["%d" % i for i in clkpol]), file=dsc_f) print("endbram", file=dsc_f) print("match bram_%02d_%02d" % (k1, k2), file=dsc_f) + if or_next: + print(" or_next_if_better", file=dsc_f) print("endmatch", file=dsc_f) states = set() @@ -252,6 +254,7 @@ for k1 in range(5): for f in [sim_f, ref_f, tb_f]: print("`timescale 1 ns / 1 ns", file=f) - for k2 in range(1 if debug_mode else 10): - create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2) + lenk2 = 1 if debug_mode else 10 + for k2 in range(lenk2): + create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2, random.randrange(2 if k2+1 < lenk2 else 1)) From 45918b8315423cb91400a0127550a1d54220c447 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 3 Jan 2015 17:40:20 +0100 Subject: [PATCH 260/492] Added "memory -bram" --- passes/memory/memory.cc | 13 +++++++++++-- tests/bram/run-single.sh | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/passes/memory/memory.cc b/passes/memory/memory.cc index 502e21022..866efae77 100644 --- a/passes/memory/memory.cc +++ b/passes/memory/memory.cc @@ -31,7 +31,7 @@ struct MemoryPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" memory [-nomap] [selection]\n"); + log(" memory [-nomap] [-bram ] [selection]\n"); log("\n"); log("This pass calls all the other memory_* passes in a useful order:\n"); log("\n"); @@ -40,7 +40,8 @@ struct MemoryPass : public Pass { log(" memory_share\n"); log(" opt_clean\n"); log(" memory_collect\n"); - log(" memory_map (skipped if called with -nomap)\n"); + log(" memory_bram -rules (when called with -bram)\n"); + log(" memory_map (skipped if called with -nomap)\n"); log("\n"); log("This converts memories to word-wide DFFs and address decoders\n"); log("or multiport memory blocks if called with the -nomap option.\n"); @@ -49,6 +50,7 @@ struct MemoryPass : public Pass { virtual void execute(std::vector args, RTLIL::Design *design) { bool flag_nomap = false; + string memory_bram_opts; log_header("Executing MEMORY pass.\n"); log_push(); @@ -59,6 +61,10 @@ struct MemoryPass : public Pass { flag_nomap = true; continue; } + if (argidx+1 < args.size() && args[argidx] == "-bram") { + memory_bram_opts += " -rules " + args[++argidx]; + continue; + } break; } extra_args(args, argidx, design); @@ -69,6 +75,9 @@ struct MemoryPass : public Pass { Pass::call(design, "opt_clean"); Pass::call(design, "memory_collect"); + if (!memory_bram_opts.empty()) + Pass::call(design, "memory_bram" + memory_bram_opts); + if (!flag_nomap) Pass::call(design, "memory_map"); diff --git a/tests/bram/run-single.sh b/tests/bram/run-single.sh index cb8295d1b..19a235c7a 100644 --- a/tests/bram/run-single.sh +++ b/tests/bram/run-single.sh @@ -1,6 +1,6 @@ #!/bin/bash set -e -../../yosys -qq -p "proc; opt; memory -nomap; memory_bram -rules temp/brams_${2}.txt; opt -fast -full" \ +../../yosys -qq -p "proc; opt; memory -nomap -bram temp/brams_${2}.txt; opt -fast -full" \ -l temp/synth_${1}_${2}.log -o temp/synth_${1}_${2}.v temp/brams_${1}.v iverilog -Dvcd_file=\"temp/tb_${1}_${2}.vcd\" -DSIMLIB_MEMDELAY=1ns -o temp/tb_${1}_${2}.tb temp/brams_${1}_tb.v \ temp/brams_${1}_ref.v temp/synth_${1}_${2}.v temp/brams_${2}.v ../../techlibs/common/simlib.v From f9304e6c10713f713a17f280507f045451863246 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 3 Jan 2015 22:10:33 +0100 Subject: [PATCH 261/492] Print non-errors to stdout --- kernel/driver.cc | 6 ++++-- kernel/log.cc | 6 ++++++ kernel/log.h | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index f1bf0657b..2cbdba8f3 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -268,8 +268,10 @@ int main(int argc, char **argv) } } - if (log_errfile == NULL) - log_files.push_back(stderr); + if (log_errfile == NULL) { + log_files.push_back(stdout); + log_error_stderr = true; + } if (print_banner) { log("\n"); diff --git a/kernel/log.cc b/kernel/log.cc index b984f0112..2be425ffd 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -44,6 +44,7 @@ FILE *log_errfile = NULL; SHA1 *log_hasher = NULL; bool log_time = false; +bool log_error_stderr = false; bool log_cmd_error_throw = false; bool log_quiet_warnings = false; int log_verbose_level; @@ -175,6 +176,11 @@ void logv_error(const char *format, va_list ap) if (log_errfile != NULL) log_files.push_back(log_errfile); + if (log_error_stderr) + for (auto &f : log_files) + if (f == stdout) + f = stderr; + log("ERROR: "); logv(format, ap); log_flush(); diff --git a/kernel/log.h b/kernel/log.h index 8096758f6..fa02d2396 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -46,6 +46,7 @@ extern FILE *log_errfile; extern SHA1 *log_hasher; extern bool log_time; +extern bool log_error_stderr; extern bool log_cmd_error_throw; extern bool log_quiet_warnings; extern int log_verbose_level; From 0648e2874c9823e8b4012877b49dfa6eef3d7034 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 4 Jan 2015 11:45:39 +0100 Subject: [PATCH 262/492] Fixed pattern matching in "hierarchy -generate" --- passes/hierarchy/hierarchy.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 66d660324..58b796a62 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -32,7 +32,7 @@ PRIVATE_NAMESPACE_BEGIN struct generate_port_decl_t { bool input, output; - RTLIL::IdString portname; + string portname; int index; }; @@ -101,7 +101,7 @@ void generate(RTLIL::Design *design, const std::vector &celltypes, for (auto &decl : portdecls) if (decl.index == 0 && patmatch(decl.portname.c_str(), RTLIL::unescape_id(portname).c_str())) { generate_port_decl_t d = decl; - d.portname = portname; + d.portname = portname.str(); d.index = *indices.begin(); log_assert(!indices.empty()); indices.erase(d.index); From 5d631f0ea74dc2507436cf315d13446e35c62cc3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 4 Jan 2015 11:46:04 +0100 Subject: [PATCH 263/492] Removed left over debug code from memory_bram --- passes/memory/memory_bram.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 868289892..b63e5e7b9 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -676,8 +676,8 @@ void handle_cell(Cell *cell, const rules_t &rules) int efficiency = (100 * match_properties["bits"]) / (dups * cells * bram.dbits * (1 << bram.abits)); match_properties["efficiency"] = efficiency; - log(" Metrics for %s: awaste=%d dwaste=%d bwaste=%d waste=%d efficiency=%d %d\n", - log_id(match.name), awaste, dwaste, bwaste, waste, efficiency, cells); + log(" Metrics for %s: awaste=%d dwaste=%d bwaste=%d waste=%d efficiency=%d\n", + log_id(match.name), awaste, dwaste, bwaste, waste, efficiency); for (auto it : match.min_limits) { if (it.first == "waste" || it.first == "dups") From daae35319be6c8f8905f25826a8f5960cdfeda20 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 4 Jan 2015 13:14:30 +0100 Subject: [PATCH 264/492] Added memory_bram "shuffle_enable" feature --- passes/memory/memory_bram.cc | 114 ++++++++++++++++++++++++++++++++++- tests/bram/generate.py | 4 ++ 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index b63e5e7b9..9e61c7f39 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -64,6 +64,7 @@ struct rules_t IdString name; dict min_limits, max_limits; bool or_next_if_better; + int shuffle_enable; }; dict brams; @@ -176,6 +177,7 @@ struct rules_t match_t data; data.name = RTLIL::escape_id(tokens[1]); data.or_next_if_better = false; + data.shuffle_enable = 0; while (next_line()) { @@ -194,6 +196,11 @@ struct rules_t continue; } + if (GetSize(tokens) == 2 && tokens[0] == "shuffle_enable") { + data.shuffle_enable = atoi(tokens[1].c_str()); + continue; + } + if (GetSize(tokens) == 1 && tokens[0] == "or_next_if_better") { data.or_next_if_better = true; continue; @@ -284,6 +291,98 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ SigSpec rd_data = cell->getPort("\\RD_DATA"); SigSpec rd_addr = cell->getPort("\\RD_ADDR"); + if (match.shuffle_enable) + { + int bucket_size = bram.dbits / match.shuffle_enable; + log(" Shuffle enable and data bit to accommodate enable buckets of size %d..\n", bucket_size); + + // extract unshuffled data/enable bits + + std::vector old_wr_en; + std::vector old_wr_data; + std::vector old_rd_data; + + for (int i = 0; i < wr_ports; i++) { + old_wr_en.push_back(wr_en.extract(i*mem_width, mem_width)); + old_wr_data.push_back(wr_data.extract(i*mem_width, mem_width)); + } + + for (int i = 0; i < rd_ports; i++) + old_rd_data.push_back(rd_data.extract(i*mem_width, mem_width)); + + // analyze enable structure + + std::vector en_order; + dict> bits_wr_en; + + for (int i = 0; i < mem_width; i++) { + SigSpec sig; + for (int j = 0; j < wr_ports; j++) + sig.append(old_wr_en[j][i]); + if (bits_wr_en.count(sig) == 0) + en_order.push_back(sig); + bits_wr_en[sig].push_back(i); + } + + // re-create memory ports + + std::vector new_wr_en(GetSize(old_wr_en)); + std::vector new_wr_data(GetSize(old_wr_data)); + std::vector new_rd_data(GetSize(old_rd_data)); + std::vector shuffle_map; + + for (auto &it : en_order) + { + auto &bits = bits_wr_en.at(it); + int buckets = (GetSize(bits) + bucket_size - 1) / bucket_size; + int fillbits = buckets*bucket_size - GetSize(bits); + SigBit fillbit; + + for (int i = 0; i < GetSize(bits); i++) { + for (int j = 0; j < wr_ports; j++) { + new_wr_en[j].append(old_wr_en[j][bits[i]]); + new_wr_data[j].append(old_wr_data[j][bits[i]]); + fillbit = old_wr_en[j][bits[i]]; + } + for (int j = 0; j < rd_ports; j++) + new_rd_data[j].append(old_rd_data[j][bits[i]]); + shuffle_map.push_back(bits[i]); + } + + for (int i = 0; i < fillbits; i++) { + for (int j = 0; j < wr_ports; j++) { + new_wr_en[j].append(fillbit); + new_wr_data[j].append(State::Sx); + } + for (int j = 0; j < rd_ports; j++) + new_rd_data[j].append(State::Sx); + shuffle_map.push_back(-1); + } + } + + log(" Results of enable shuffling:"); + for (int v : shuffle_map) + log(" %d", v); + log("\n"); + + // update mem_*, wr_*, and rd_* variables + + mem_width = GetSize(new_wr_en.front()); + wr_en = SigSpec(0, wr_ports * mem_width); + wr_data = SigSpec(0, wr_ports * mem_width); + rd_data = SigSpec(0, rd_ports * mem_width); + + for (int i = 0; i < wr_ports; i++) { + wr_en.replace(i*mem_width, new_wr_en[i]); + wr_data.replace(i*mem_width, new_wr_data[i]); + } + + for (int i = 0; i < rd_ports; i++) + rd_data.replace(i*mem_width, new_rd_data[i]); + } + + // assign write ports + for (int cell_port_i = 0, bram_port_i = 0; cell_port_i < wr_ports; cell_port_i++) { bool clken = wr_clken[cell_port_i] == State::S1; @@ -334,6 +433,7 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ sig_en.append(last_en_bit); } if (last_en_bit != wr_en[i + cell_port_i*mem_width]) { + log_dump(last_en_bit, wr_en[i + cell_port_i*mem_width]); log(" Bram port %c%d has incompatible enable structure.\n", pi.group + 'A', pi.index + 1); goto skip_bram_wport; } @@ -362,6 +462,8 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ mapped_wr_port:; } + // houskeeping stuff for growing more read ports and restarting read port assignments + int grow_read_ports_cursor = -1; bool try_growing_more_read_ports = false; auto backup_clock_domains = clock_domains; @@ -401,6 +503,8 @@ grow_read_ports:; read_transp[0] = false; read_transp[1] = true; + // assign read ports + for (int cell_port_i = 0; cell_port_i < rd_ports; cell_port_i++) { bool clken = rd_clken[cell_port_i] == State::S1; @@ -479,12 +583,14 @@ grow_read_ports:; mapped_rd_port:; } + // update properties and re-check conditions + if (mode <= 1) { match_properties["dups"] = dup_count; match_properties["waste"] = match_properties["dups"] * match_properties["bwaste"]; - int cells = ((match_properties["dbits"] + bram.dbits - 1) / bram.dbits) * ((match_properties["words"] + (1 << bram.abits) - 1) / (1 << bram.abits)); + int cells = ((mem_width + bram.dbits - 1) / bram.dbits) * ((mem_size + (1 << bram.abits) - 1) / (1 << bram.abits)); match_properties["efficiency"] = (100 * match_properties["bits"]) / (dup_count * cells * bram.dbits * (1 << bram.abits)); log(" Updated properties: dups=%d waste=%d efficiency=%d\n", @@ -515,6 +621,8 @@ grow_read_ports:; return true; } + // actually replace that memory cell + dict> dout_cache; for (int grid_d = 0; grid_d*bram.dbits < mem_width; grid_d++) @@ -825,6 +933,10 @@ struct MemoryBramPass : public Pass { log("has a higher efficiency than the next match (and the one after that if\n"); log("the next also has 'or_next_if_better' set, and so forth).\n"); log("\n"); + log("A match containing the command 'shuffle_enable ' will re-organize\n"); + log("the data bits to accommodate bram ports with enable bits before\n"); + log("mapping to the bram.\n"); + log("\n"); } virtual void execute(vector args, Design *design) { diff --git a/tests/bram/generate.py b/tests/bram/generate.py index 03f2555dc..4bf3a9541 100644 --- a/tests/bram/generate.py +++ b/tests/bram/generate.py @@ -68,6 +68,10 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2, or_next): print(" clkpol %s" % " ".join(["%d" % i for i in clkpol]), file=dsc_f) print("endbram", file=dsc_f) print("match bram_%02d_%02d" % (k1, k2), file=dsc_f) + if random.randrange(2): + non_zero_enables = [i for i in enable if i] + if len(non_zero_enables): + print(" shuffle_enable %d" % random.choice(non_zero_enables), file=dsc_f) if or_next: print(" or_next_if_better", file=dsc_f) print("endmatch", file=dsc_f) From 8898897f7b397a09c94e4850ef6146ee5b09677b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 4 Jan 2015 14:23:30 +0100 Subject: [PATCH 265/492] Towards Xilinx bram support --- passes/memory/memory_bram.cc | 7 +- techlibs/xilinx/Makefile.inc | 10 ++- techlibs/xilinx/brams.txt | 128 +++++++++++++++++++++++++++++++---- techlibs/xilinx/brams.v | 59 ++++++++++++++++ 4 files changed, 187 insertions(+), 17 deletions(-) create mode 100644 techlibs/xilinx/brams.v diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 9e61c7f39..efabfc06d 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -73,20 +73,21 @@ struct rules_t std::ifstream infile; vector tokens; int linecount; - string line; void syntax_error() { - if (line.empty()) + if (tokens.empty()) log_error("Unexpected end of rules file in line %d.\n", linecount); - log_error("Syntax error in rules file line %d: %s\n", linecount, line.c_str()); + log_error("Syntax error in rules file line %d.\n", linecount); } bool next_line() { linecount++; tokens.clear(); + string line; while (std::getline(infile, line)) { + log("> %s\n", line.c_str()); for (string tok = next_token(line); !tok.empty(); tok = next_token(line)) { if (tok[0] == '#') break; diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index cd19f10e7..64ee9597c 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -1,9 +1,17 @@ OBJS += techlibs/xilinx/synth_xilinx.o -EXTRA_TARGETS += share/xilinx/cells.v +EXTRA_TARGETS += share/xilinx/cells.v share/xilinx/brams.txt share/xilinx/brams.v share/xilinx/cells.v: techlibs/xilinx/cells.v $(P) mkdir -p share/xilinx $(Q) cp techlibs/xilinx/cells.v share/xilinx/cells.v +share/xilinx/brams.txt: techlibs/xilinx/brams.txt + $(P) mkdir -p share/xilinx + $(Q) cp techlibs/xilinx/brams.txt share/xilinx/brams.txt + +share/xilinx/brams.v: techlibs/xilinx/brams.v + $(P) mkdir -p share/xilinx + $(Q) cp techlibs/xilinx/brams.v share/xilinx/brams.v + diff --git a/techlibs/xilinx/brams.txt b/techlibs/xilinx/brams.txt index e5652eabf..7c5fe081f 100644 --- a/techlibs/xilinx/brams.txt +++ b/techlibs/xilinx/brams.txt @@ -1,20 +1,122 @@ -# This is a very simplified description of the capabilities of -# the Xilinx RAMB36 core. But it is a start.. -# -bram XILINX_RAMB36_SDP32 - init 1 - abits 10 - dbits 32 +bram $__XILINX_RAMB36_SDP72 + abits 9 + dbits 72 groups 2 ports 1 1 - wrmode 1 0 - enable 4 0 - transp 0 2 - clocks 1 2 + wrmode 0 1 + enable 0 8 + transp 2 0 + clocks 2 3 + clkpol 2 3 endbram -match XILINX_RAMB36_SDP32 - min bits 1024 +bram $__XILINX_RAMB36_SDP36 + abits 10 + dbits 36 + groups 2 + ports 1 1 + wrmode 0 1 + enable 0 4 + transp 2 0 + clocks 2 3 + clkpol 2 3 +endbram + +bram $__XILINX_RAMB36_SDP18 + abits 11 + dbits 18 + groups 2 + ports 1 1 + wrmode 0 1 + enable 0 2 + transp 2 0 + clocks 2 3 + clkpol 2 3 +endbram + +bram $__XILINX_RAMB36_SDP9 + abits 12 + dbits 9 + groups 2 + ports 1 1 + wrmode 0 1 + enable 0 1 + transp 2 0 + clocks 2 3 + clkpol 2 3 +endbram + +bram $__XILINX_RAMB36_SDP4 + abits 13 + dbits 4 + groups 2 + ports 1 1 + wrmode 0 1 + enable 0 1 + transp 2 0 + clocks 2 3 + clkpol 2 3 +endbram + +bram $__XILINX_RAMB36_SDP2 + abits 14 + dbits 2 + groups 2 + ports 1 1 + wrmode 0 1 + enable 0 1 + transp 2 0 + clocks 2 3 + clkpol 2 3 +endbram + +bram $__XILINX_RAMB36_SDP1 + abits 15 + dbits 1 + groups 2 + ports 1 1 + wrmode 0 1 + enable 0 1 + transp 2 0 + clocks 2 3 + clkpol 2 3 +endbram + +match $__XILINX_RAMB36_SDP72 + shuffle_enable 8 + min efficiency 20 + # or_next_if_better endmatch +# match $__XILINX_RAMB36_SDP36 +# shuffle_enable 4 +# min efficiency 20 +# or_next_if_better +# endmatch +# +# match $__XILINX_RAMB36_SDP18 +# shuffle_enable 2 +# min efficiency 20 +# or_next_if_better +# endmatch +# +# match $__XILINX_RAMB36_SDP9 +# min efficiency 20 +# or_next_if_better +# endmatch +# +# match $__XILINX_RAMB36_SDP4 +# min efficiency 20 +# or_next_if_better +# endmatch +# +# match $__XILINX_RAMB36_SDP2 +# min efficiency 20 +# or_next_if_better +# endmatch +# +# match $__XILINX_RAMB36_SDP1 +# min efficiency 20 +# endmatch + diff --git a/techlibs/xilinx/brams.v b/techlibs/xilinx/brams.v new file mode 100644 index 000000000..067ca8b28 --- /dev/null +++ b/techlibs/xilinx/brams.v @@ -0,0 +1,59 @@ +module \$__XILINX_RAMB36_SDP72 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); + parameter TRANSP2 = 1; + parameter CLKPOL2 = 1; + parameter CLKPOL3 = 1; + + input CLK2; + input CLK3; + + input [8:0] A1ADDR; + output [71:0] A1DATA; + + input [8:0] B1ADDR; + input [71:0] B1DATA; + input [7:0] B1EN; + + wire [15:0] A1ADDR_16 = A1ADDR; + wire [15:0] B1ADDR_16 = B1ADDR; + + wire [7:0] DIP, DOP; + wire [63:0] DI, DO; + + assign A1DATA = { DOP[7], DO[63:56], DOP[6], DO[55:48], DOP[5], DO[47:40], DOP[4], DO[39:32], + DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; + + assign { DIP[7], DI[63:56], DIP[6], DI[55:48], DIP[5], DI[47:40], DIP[4], DI[39:32], + DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; + + RAMB36E1 #( + .RAM_MODE("SDP"), + .READ_WIDTH_A(72), + .WRITE_WIDTH_B(72), + .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") + ) _TECHMAP_REPLACE_ ( + .DOBDO(DO[63:32]), + .DOADO(DO[31:0]), + .DOPBDOP(DOP[7:4]), + .DOPADOP(DOP[3:0]), + .DIBDI(DI[63:32]), + .DIADI(DI[31:0]), + .DIPBDIP(DIP[7:4]), + .DIPADIP(DIP[3:0]), + + .ADDRARDADDR(A1ADDR_16), + .CLKARDCLK(CLK2 == |CLKPOL2), + .ENARDEN(|1), + .REGCEAREGCE(|1), + .RSTRAMARSTRAM(|0), + .RSTREGARSTREG(|0), + .WEA(4'b0), + + .ADDRBWRADDR(B1ADDR_16), + .CLKBWRCLK(CLK3 == |CLKPOL3), + .ENBWREN(|1), + .REGCEB(|0), + .RSTRAMB(|0), + .RSTREGB(|0), + .WEBWE(B1EN) + ); +endmodule From 9ea2511fe87a9a3a4dd179101f42982ed62e78c0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 5 Jan 2015 13:59:04 +0100 Subject: [PATCH 266/492] Towards Xilinx bram support --- passes/memory/memory_bram.cc | 3 ++ techlibs/xilinx/brams.txt | 2 +- techlibs/xilinx/brams.v | 5 ++- techlibs/xilinx/synth_xilinx.cc | 36 +++++++++------- techlibs/xilinx/tests/.gitignore | 3 ++ techlibs/xilinx/tests/bram1.sh | 48 +++++++++++++++++++++ techlibs/xilinx/tests/bram1.v | 24 +++++++++++ techlibs/xilinx/tests/bram1_tb.v | 73 ++++++++++++++++++++++++++++++++ 8 files changed, 175 insertions(+), 19 deletions(-) create mode 100644 techlibs/xilinx/tests/.gitignore create mode 100644 techlibs/xilinx/tests/bram1.sh create mode 100644 techlibs/xilinx/tests/bram1.v create mode 100644 techlibs/xilinx/tests/bram1_tb.v diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index efabfc06d..e7a42f26d 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -215,6 +215,9 @@ struct rules_t void parse(string filename) { + if (filename.substr(0, 2) == "+/") + filename = proc_share_dirname() + filename.substr(1); + infile.open(filename); linecount = 0; diff --git a/techlibs/xilinx/brams.txt b/techlibs/xilinx/brams.txt index 7c5fe081f..69214fd59 100644 --- a/techlibs/xilinx/brams.txt +++ b/techlibs/xilinx/brams.txt @@ -85,7 +85,7 @@ endbram match $__XILINX_RAMB36_SDP72 shuffle_enable 8 - min efficiency 20 + # min efficiency 20 # or_next_if_better endmatch diff --git a/techlibs/xilinx/brams.v b/techlibs/xilinx/brams.v index 067ca8b28..aaab8d475 100644 --- a/techlibs/xilinx/brams.v +++ b/techlibs/xilinx/brams.v @@ -29,6 +29,7 @@ module \$__XILINX_RAMB36_SDP72 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .RAM_MODE("SDP"), .READ_WIDTH_A(72), .WRITE_WIDTH_B(72), + .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"), .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") ) _TECHMAP_REPLACE_ ( .DOBDO(DO[63:32]), @@ -41,7 +42,7 @@ module \$__XILINX_RAMB36_SDP72 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .DIPADIP(DIP[3:0]), .ADDRARDADDR(A1ADDR_16), - .CLKARDCLK(CLK2 == |CLKPOL2), + .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), .ENARDEN(|1), .REGCEAREGCE(|1), .RSTRAMARSTRAM(|0), @@ -49,7 +50,7 @@ module \$__XILINX_RAMB36_SDP72 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .WEA(4'b0), .ADDRBWRADDR(B1ADDR_16), - .CLKBWRCLK(CLK3 == |CLKPOL3), + .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), .ENBWREN(|1), .REGCEB(|0), .RSTRAMB(|0), diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 8df5c4e42..7b7dbd0fd 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -69,25 +69,26 @@ struct SynthXilinxPass : public Pass { log(" hierarchy -check -top \n"); log("\n"); log(" coarse:\n"); - log(" proc\n"); - log(" opt\n"); - log(" memory\n"); - log(" clean\n"); - log(" fsm\n"); - log(" opt\n"); + log(" synth -run coarse\n"); + log(" memory_bram -rules +/xilinx/brams.txt\n"); + log(" techmap -map +/xilinx/brams.v\n"); log("\n"); log(" fine:\n"); log(" techmap\n"); - log(" opt\n"); + log(" opt -fast -full\n"); log("\n"); log(" map_luts:\n"); log(" abc -lut 6\n"); log(" clean\n"); log("\n"); log(" map_cells:\n"); - log(" techmap -share_map xilinx/cells.v\n"); + log(" techmap -map +/xilinx/cells.v\n"); log(" clean\n"); log("\n"); + log(" flatten:\n"); + log(" flatten\n"); + log(" opt -fast -full\n"); + log("\n"); log(" clkbuf:\n"); log(" select -set xilinx_clocks /t:FDRE %%x:+FDRE[C] /t:FDRE %%d\n"); log(" iopadmap -inpad BUFGP O:I @xilinx_clocks\n"); @@ -163,18 +164,15 @@ struct SynthXilinxPass : public Pass { if (check_label(active, run_from, run_to, "coarse")) { - Pass::call(design, "proc"); - Pass::call(design, "opt"); - Pass::call(design, "memory"); - Pass::call(design, "clean"); - Pass::call(design, "fsm"); - Pass::call(design, "opt"); + Pass::call(design, "synth -run coarse"); + Pass::call(design, "memory_bram -rules +/xilinx/brams.txt"); + Pass::call(design, "techmap -map +/xilinx/brams.v"); } if (check_label(active, run_from, run_to, "fine")) { Pass::call(design, "techmap"); - Pass::call(design, "opt"); + Pass::call(design, "opt -fast -full"); } if (check_label(active, run_from, run_to, "map_luts")) @@ -185,10 +183,16 @@ struct SynthXilinxPass : public Pass { if (check_label(active, run_from, run_to, "map_cells")) { - Pass::call(design, "techmap -share_map xilinx/cells.v"); + Pass::call(design, "techmap -map +/xilinx/cells.v"); Pass::call(design, "clean"); } + if (check_label(active, run_from, run_to, "flatten")) + { + Pass::call(design, "flatten"); + Pass::call(design, "opt -fast -full"); + } + if (check_label(active, run_from, run_to, "clkbuf")) { Pass::call(design, stringf("select -set xilinx_clocks %s/t:FDRE %%x:+FDRE[C] %s/t:FDRE %%d", top_module.c_str(), top_module.c_str())); diff --git a/techlibs/xilinx/tests/.gitignore b/techlibs/xilinx/tests/.gitignore new file mode 100644 index 000000000..bc2f8babf --- /dev/null +++ b/techlibs/xilinx/tests/.gitignore @@ -0,0 +1,3 @@ +bram1_cmp +bram1.mk +bram1_[0-9]*/ diff --git a/techlibs/xilinx/tests/bram1.sh b/techlibs/xilinx/tests/bram1.sh new file mode 100644 index 000000000..3a72cce48 --- /dev/null +++ b/techlibs/xilinx/tests/bram1.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +echo "all: all_list" > bram1.mk +all_list="all_list:" + +for transp in 0 1; do +for abits in 1 2 4 8 10 16 20; do +for dbits in 1 2 4 8 10 16 20 24 30 32 40 48 50 56 60 64 70 72 80; do + if [ $(( (1 << $abits) * $dbits )) -gt 1000000 ]; then continue; fi + if [ $(( (1 << $abits) * $dbits )) -gt 100 ]; then continue; fi + id=`printf "%d%02d%02d" $transp $abits $dbits` + echo "Creating bram1_$id.." + rm -rf bram1_$id + mkdir -p bram1_$id + cp bram1.v bram1_tb.v bram1_$id/ + sed -i "/parameter/ s,ABITS *= *[0-9]*,ABITS = $abits," bram1_$id/*.v + sed -i "/parameter/ s,DBITS *= *[0-9]*,DBITS = $dbits," bram1_$id/*.v + sed -i "/parameter/ s,TRANSP *= *[0-9]*,TRANSP = $transp," bram1_$id/*.v + { + echo "set -e" + echo "../../../../yosys -q -lsynth.log -p 'synth_xilinx -top bram1; write_verilog synth.v' bram1.v" + echo "xvlog --work gold bram1_tb.v bram1.v > gold.txt" + echo "xvlog --work gate bram1_tb.v synth.v > gate.txt" + echo "xelab -R gold.bram1_tb >> gold.txt" + echo "mv testbench.vcd gold.vcd" + echo "xelab -L unisim -R gate.bram1_tb >> gate.txt" + echo "mv testbench.vcd gate.vcd" + echo "../bram1_cmp <( grep '#OUT#' gold.txt; ) <( grep '#OUT#' gate.txt; )" + } > bram1_$id/run.sh + { + echo "bram1_$id/ok:" + echo " @cd bram1_$id && bash run.sh" + echo " @echo -n '[$id]'" + echo " @touch \$@" + } >> bram1.mk + all_list="$all_list bram1_$id/ok" +done; done; done + +cc -o bram1_cmp ../../../tests/tools/cmp_tbdata.c +echo "$all_list" >> bram1.mk + +echo "Testing..." +${MAKE:-make} -f bram1.mk +echo + +# echo "Cleaning up..." +# rm -rf bram1_cmp bram1.mk bram1_[0-9]*/ + diff --git a/techlibs/xilinx/tests/bram1.v b/techlibs/xilinx/tests/bram1.v new file mode 100644 index 000000000..034cc18e9 --- /dev/null +++ b/techlibs/xilinx/tests/bram1.v @@ -0,0 +1,24 @@ +module bram1 #( + parameter ABITS = 8, DBITS = 8, TRANSP = 0 +) ( + input clk, + + input [ABITS-1:0] WR_ADDR, + input [DBITS-1:0] WR_DATA, + input WR_EN, + + input [ABITS-1:0] RD_ADDR, + output [DBITS-1:0] RD_DATA +); + reg [DBITS-1:0] memory [0:2**ABITS-1]; + reg [ABITS-1:0] RD_ADDR_BUF; + reg [DBITS-1:0] RD_DATA_BUF; + + always @(posedge clk) begin + if (WR_EN) memory[WR_ADDR] <= WR_DATA; + RD_ADDR_BUF <= RD_ADDR; + RD_DATA_BUF <= memory[RD_ADDR]; + end + + assign RD_DATA = TRANSP ? memory[RD_ADDR_BUF] : RD_DATA_BUF; +endmodule diff --git a/techlibs/xilinx/tests/bram1_tb.v b/techlibs/xilinx/tests/bram1_tb.v new file mode 100644 index 000000000..98e6bafe6 --- /dev/null +++ b/techlibs/xilinx/tests/bram1_tb.v @@ -0,0 +1,73 @@ +module bram1_tb #( + parameter ABITS = 8, DBITS = 8, TRANSP = 0 +); + reg clk; + reg [ABITS-1:0] WR_ADDR; + reg [DBITS-1:0] WR_DATA; + reg WR_EN; + reg [ABITS-1:0] RD_ADDR; + wire [DBITS-1:0] RD_DATA; + + bram1 #( + // .ABITS(ABITS), + // .DBITS(DBITS), + // .TRANSP(TRANSP) + ) uut ( + .clk (clk ), + .WR_ADDR(WR_ADDR), + .WR_DATA(WR_DATA), + .WR_EN (WR_EN ), + .RD_ADDR(RD_ADDR), + .RD_DATA(RD_DATA) + ); + + function [31:0] getaddr(input [3:0] n); + begin + case (n) + 0: getaddr = 0; + 1: getaddr = 2**ABITS-1; + 2: getaddr = 'b101 << (ABITS / 3); + 3: getaddr = 'b101 << (2*ABITS / 3); + 4: getaddr = 'b11011 << (ABITS / 4); + 5: getaddr = 'b11011 << (2*ABITS / 4); + 6: getaddr = 'b11011 << (3*ABITS / 4); + 7: getaddr = 123456789; + default: getaddr = 1 << (2*n-16); + endcase + end + endfunction + + reg [DBITS-1:0] memory [0:2**ABITS-1]; + reg [DBITS-1:0] expected_rd; + + integer i, j; + initial begin + $dumpfile("testbench.vcd"); + $dumpvars(0, bram1_tb); + clk <= 0; + for (i = 0; i < 256; i = i+1) begin + WR_DATA <= i; + WR_ADDR <= getaddr(i[7:4]); + RD_ADDR <= getaddr(i[3:0]); + WR_EN <= ^i; + + #1; clk <= 1; + #1; clk <= 0; + + if (TRANSP) begin + if (WR_EN) memory[WR_ADDR] = WR_DATA; + expected_rd = memory[RD_ADDR]; + end else begin + expected_rd = memory[RD_ADDR]; + if (WR_EN) memory[WR_ADDR] = WR_DATA; + end + + for (j = 0; j < DBITS; j = j+1) begin + if (expected_rd[j] === 1'bx) + expected_rd[j] = RD_DATA[j]; + end + + $display("#OUT# | WA=%x WD=%x WE=%x | RA=%x RD=%x | %s", WR_ADDR, WR_DATA, WR_EN, RD_ADDR, RD_DATA, expected_rd === RD_DATA ? "ok" : "ERROR"); + end + end +endmodule From 462b22f44fae71767991bd4eb502d009149b3995 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Jan 2015 00:16:44 +0100 Subject: [PATCH 267/492] dict<> ref vs insert bugfix --- passes/opt/opt_const.cc | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc index 7f800bde9..2eaba15ce 100644 --- a/passes/opt/opt_const.cc +++ b/passes/opt/opt_const.cc @@ -669,8 +669,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cell->unsetPort("\\B"); cell->unsetPort("\\S"); if (cell->type == "$mux") { - cell->parameters["\\A_WIDTH"] = cell->parameters["\\WIDTH"]; - cell->parameters["\\Y_WIDTH"] = cell->parameters["\\WIDTH"]; + Const width = cell->parameters["\\WIDTH"]; + cell->parameters["\\A_WIDTH"] = width; + cell->parameters["\\Y_WIDTH"] = width; cell->parameters["\\A_SIGNED"] = 0; cell->parameters.erase("\\WIDTH"); cell->type = "$not"; @@ -686,9 +687,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cell->setPort("\\A", cell->getPort("\\S")); cell->unsetPort("\\S"); if (cell->type == "$mux") { - cell->parameters["\\A_WIDTH"] = cell->parameters["\\WIDTH"]; - cell->parameters["\\B_WIDTH"] = cell->parameters["\\WIDTH"]; - cell->parameters["\\Y_WIDTH"] = cell->parameters["\\WIDTH"]; + auto width = cell->parameters["\\WIDTH"]; + cell->parameters["\\A_WIDTH"] = width; + cell->parameters["\\B_WIDTH"] = width; + cell->parameters["\\Y_WIDTH"] = width; cell->parameters["\\A_SIGNED"] = 0; cell->parameters["\\B_SIGNED"] = 0; cell->parameters.erase("\\WIDTH"); @@ -705,9 +707,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cell->setPort("\\B", cell->getPort("\\S")); cell->unsetPort("\\S"); if (cell->type == "$mux") { - cell->parameters["\\A_WIDTH"] = cell->parameters["\\WIDTH"]; - cell->parameters["\\B_WIDTH"] = cell->parameters["\\WIDTH"]; - cell->parameters["\\Y_WIDTH"] = cell->parameters["\\WIDTH"]; + auto width = cell->parameters["\\WIDTH"]; + cell->parameters["\\A_WIDTH"] = width; + cell->parameters["\\B_WIDTH"] = width; + cell->parameters["\\Y_WIDTH"] = width; cell->parameters["\\A_SIGNED"] = 0; cell->parameters["\\B_SIGNED"] = 0; cell->parameters.erase("\\WIDTH"); @@ -894,8 +897,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (!swapped_ab) { cell->setPort("\\A", cell->getPort("\\B")); - cell->parameters["\\A_WIDTH"] = cell->parameters["\\B_WIDTH"]; - cell->parameters["\\A_SIGNED"] = cell->parameters["\\B_SIGNED"]; + cell->parameters.at("\\A_WIDTH") = cell->parameters.at("\\B_WIDTH"); + cell->parameters.at("\\A_SIGNED") = cell->parameters.at("\\B_SIGNED"); } std::vector new_b = RTLIL::SigSpec(i, 6); From 9c7f47bbd5fc190578054a6d018760c2f2b62c03 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Jan 2015 13:33:51 +0100 Subject: [PATCH 268/492] Towards Xilinx bram support --- techlibs/xilinx/brams.v | 4 ++-- techlibs/xilinx/tests/bram1.sh | 4 ++-- techlibs/xilinx/tests/bram1_tb.v | 8 ++++++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/brams.v b/techlibs/xilinx/brams.v index aaab8d475..49219c8a1 100644 --- a/techlibs/xilinx/brams.v +++ b/techlibs/xilinx/brams.v @@ -13,8 +13,8 @@ module \$__XILINX_RAMB36_SDP72 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN input [71:0] B1DATA; input [7:0] B1EN; - wire [15:0] A1ADDR_16 = A1ADDR; - wire [15:0] B1ADDR_16 = B1ADDR; + wire [15:0] A1ADDR_16 = {A1ADDR, 6'b0}; + wire [15:0] B1ADDR_16 = {B1ADDR, 6'b0}; wire [7:0] DIP, DOP; wire [63:0] DI, DO; diff --git a/techlibs/xilinx/tests/bram1.sh b/techlibs/xilinx/tests/bram1.sh index 3a72cce48..fe807ad8f 100644 --- a/techlibs/xilinx/tests/bram1.sh +++ b/techlibs/xilinx/tests/bram1.sh @@ -22,9 +22,9 @@ for dbits in 1 2 4 8 10 16 20 24 30 32 40 48 50 56 60 64 70 72 80; do echo "xvlog --work gold bram1_tb.v bram1.v > gold.txt" echo "xvlog --work gate bram1_tb.v synth.v > gate.txt" echo "xelab -R gold.bram1_tb >> gold.txt" - echo "mv testbench.vcd gold.vcd" + # echo "mv testbench.vcd gold.vcd" echo "xelab -L unisim -R gate.bram1_tb >> gate.txt" - echo "mv testbench.vcd gate.vcd" + # echo "mv testbench.vcd gate.vcd" echo "../bram1_cmp <( grep '#OUT#' gold.txt; ) <( grep '#OUT#' gate.txt; )" } > bram1_$id/run.sh { diff --git a/techlibs/xilinx/tests/bram1_tb.v b/techlibs/xilinx/tests/bram1_tb.v index 98e6bafe6..c14cf6e30 100644 --- a/techlibs/xilinx/tests/bram1_tb.v +++ b/techlibs/xilinx/tests/bram1_tb.v @@ -40,10 +40,13 @@ module bram1_tb #( reg [DBITS-1:0] memory [0:2**ABITS-1]; reg [DBITS-1:0] expected_rd; + event error; + reg error_ind = 0; + integer i, j; initial begin - $dumpfile("testbench.vcd"); - $dumpvars(0, bram1_tb); + // $dumpfile("testbench.vcd"); + // $dumpvars(0, bram1_tb); clk <= 0; for (i = 0; i < 256; i = i+1) begin WR_DATA <= i; @@ -68,6 +71,7 @@ module bram1_tb #( end $display("#OUT# | WA=%x WD=%x WE=%x | RA=%x RD=%x | %s", WR_ADDR, WR_DATA, WR_EN, RD_ADDR, RD_DATA, expected_rd === RD_DATA ? "ok" : "ERROR"); + if (expected_rd !== RD_DATA) begin -> error; error_ind = ~error_ind; end end end endmodule From 081e1a49f81c298a5c30c4b51241d50ce64f185e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Jan 2015 14:26:51 +0100 Subject: [PATCH 269/492] Towards Xilinx bram support --- passes/memory/memory_bram.cc | 2 +- techlibs/xilinx/brams.v | 25 +++++++++++++++++++++++-- techlibs/xilinx/tests/bram1.sh | 29 ++++++++++++++++++----------- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index e7a42f26d..fd5db188e 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -356,7 +356,7 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ for (int i = 0; i < fillbits; i++) { for (int j = 0; j < wr_ports; j++) { new_wr_en[j].append(fillbit); - new_wr_data[j].append(State::Sx); + new_wr_data[j].append(State::S0); } for (int j = 0; j < rd_ports; j++) new_rd_data[j].append(State::Sx); diff --git a/techlibs/xilinx/brams.v b/techlibs/xilinx/brams.v index 49219c8a1..f98625bfa 100644 --- a/techlibs/xilinx/brams.v +++ b/techlibs/xilinx/brams.v @@ -19,8 +19,29 @@ module \$__XILINX_RAMB36_SDP72 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN wire [7:0] DIP, DOP; wire [63:0] DI, DO; - assign A1DATA = { DOP[7], DO[63:56], DOP[6], DO[55:48], DOP[5], DO[47:40], DOP[4], DO[39:32], - DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; + wire [71:0] A1DATA_BUF; + reg [71:0] B1DATA_Q; + reg [7:0] transparent_cycle; + + wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast"; + + generate if (CLKPOL2) + always @(posedge CLK2) begin transparent_cycle <= TRANSP2 && A1ADDR == B1ADDR ? B1EN : 0; B1DATA_Q <= B1DATA; end + else + always @(negedge CLK2) begin transparent_cycle <= TRANSP2 && A1ADDR == B1ADDR ? B1EN : 0; B1DATA_Q <= B1DATA; end + endgenerate + + assign A1DATA[ 8: 0] = transparent_cycle[0] ? B1DATA_Q[ 8: 0] : A1DATA_BUF[ 8: 0]; + assign A1DATA[17: 9] = transparent_cycle[1] ? B1DATA_Q[17: 9] : A1DATA_BUF[17: 9]; + assign A1DATA[26:18] = transparent_cycle[2] ? B1DATA_Q[26:18] : A1DATA_BUF[26:18]; + assign A1DATA[35:27] = transparent_cycle[3] ? B1DATA_Q[35:27] : A1DATA_BUF[35:27]; + assign A1DATA[44:36] = transparent_cycle[4] ? B1DATA_Q[44:36] : A1DATA_BUF[44:36]; + assign A1DATA[53:45] = transparent_cycle[5] ? B1DATA_Q[53:45] : A1DATA_BUF[53:45]; + assign A1DATA[62:54] = transparent_cycle[6] ? B1DATA_Q[62:54] : A1DATA_BUF[62:54]; + assign A1DATA[71:63] = transparent_cycle[7] ? B1DATA_Q[71:63] : A1DATA_BUF[71:63]; + + assign A1DATA_BUF = { DOP[7], DO[63:56], DOP[6], DO[55:48], DOP[5], DO[47:40], DOP[4], DO[39:32], + DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; assign { DIP[7], DI[63:56], DIP[6], DI[55:48], DIP[5], DI[47:40], DIP[4], DI[39:32], DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; diff --git a/techlibs/xilinx/tests/bram1.sh b/techlibs/xilinx/tests/bram1.sh index fe807ad8f..f233be9fa 100644 --- a/techlibs/xilinx/tests/bram1.sh +++ b/techlibs/xilinx/tests/bram1.sh @@ -1,13 +1,15 @@ #!/bin/bash +use_xsim=false +unisims=/opt/Xilinx/Vivado/2014.4/data/verilog/src/unisims + echo "all: all_list" > bram1.mk -all_list="all_list:" +all_list="" for transp in 0 1; do for abits in 1 2 4 8 10 16 20; do for dbits in 1 2 4 8 10 16 20 24 30 32 40 48 50 56 60 64 70 72 80; do if [ $(( (1 << $abits) * $dbits )) -gt 1000000 ]; then continue; fi - if [ $(( (1 << $abits) * $dbits )) -gt 100 ]; then continue; fi id=`printf "%d%02d%02d" $transp $abits $dbits` echo "Creating bram1_$id.." rm -rf bram1_$id @@ -19,12 +21,17 @@ for dbits in 1 2 4 8 10 16 20 24 30 32 40 48 50 56 60 64 70 72 80; do { echo "set -e" echo "../../../../yosys -q -lsynth.log -p 'synth_xilinx -top bram1; write_verilog synth.v' bram1.v" - echo "xvlog --work gold bram1_tb.v bram1.v > gold.txt" - echo "xvlog --work gate bram1_tb.v synth.v > gate.txt" - echo "xelab -R gold.bram1_tb >> gold.txt" - # echo "mv testbench.vcd gold.vcd" - echo "xelab -L unisim -R gate.bram1_tb >> gate.txt" - # echo "mv testbench.vcd gate.vcd" + if $use_xsim; then + echo "xvlog --work gold bram1_tb.v bram1.v > gold.txt" + echo "xvlog --work gate bram1_tb.v synth.v > gate.txt" + echo "xelab -R gold.bram1_tb >> gold.txt" + echo "xelab -L unisim -R gate.bram1_tb >> gate.txt" + else + echo "iverilog -o bram1_tb_gold bram1_tb.v bram1.v > gold.txt 2>&1" + echo "iverilog -o bram1_tb_gate bram1_tb.v synth.v -y $unisims $unisims/../glbl.v > gate.txt 2>&1" + echo "./bram1_tb_gold >> gold.txt" + echo "./bram1_tb_gate >> gate.txt" + fi echo "../bram1_cmp <( grep '#OUT#' gold.txt; ) <( grep '#OUT#' gate.txt; )" } > bram1_$id/run.sh { @@ -37,12 +44,12 @@ for dbits in 1 2 4 8 10 16 20 24 30 32 40 48 50 56 60 64 70 72 80; do done; done; done cc -o bram1_cmp ../../../tests/tools/cmp_tbdata.c -echo "$all_list" >> bram1.mk +echo all_list: $(echo $all_list | tr ' ' '\n' | sort -R) >> bram1.mk echo "Testing..." ${MAKE:-make} -f bram1.mk echo -# echo "Cleaning up..." -# rm -rf bram1_cmp bram1.mk bram1_[0-9]*/ +echo "Cleaning up..." +rm -rf bram1_cmp bram1.mk bram1_[0-9]*/ From 4a0b3a5423175eed7f1de9e975ee1fb20a2eb3ae Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Jan 2015 14:37:50 +0100 Subject: [PATCH 270/492] Various small improvements to synth_xilinx --- passes/techmap/iopadmap.cc | 4 ++-- techlibs/xilinx/synth_xilinx.cc | 14 ++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc index 76d6115ae..75d02c828 100644 --- a/passes/techmap/iopadmap.cc +++ b/passes/techmap/iopadmap.cc @@ -62,8 +62,8 @@ struct IopadmapPass : public Pass { log("\n"); log(" -bits\n"); log(" create individual bit-wide buffers even for ports that\n"); - log(" are wider. (the default behavio is to create word-wide\n"); - log(" buffers use -widthparam to set the word size on the cell.)\n"); + log(" are wider. (the default behavior is to create word-wide\n"); + log(" buffers using -widthparam to set the word size on the cell.)\n"); log("\n"); } virtual void execute(std::vector args, RTLIL::Design *design) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 7b7dbd0fd..a0783740b 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -74,8 +74,7 @@ struct SynthXilinxPass : public Pass { log(" techmap -map +/xilinx/brams.v\n"); log("\n"); log(" fine:\n"); - log(" techmap\n"); - log(" opt -fast -full\n"); + log(" synth -run fine\n"); log("\n"); log(" map_luts:\n"); log(" abc -lut 6\n"); @@ -91,11 +90,11 @@ struct SynthXilinxPass : public Pass { log("\n"); log(" clkbuf:\n"); log(" select -set xilinx_clocks /t:FDRE %%x:+FDRE[C] /t:FDRE %%d\n"); - log(" iopadmap -inpad BUFGP O:I @xilinx_clocks\n"); + log(" iopadmap -bits -inpad BUFGP O:I @xilinx_clocks\n"); log("\n"); log(" iobuf:\n"); log(" select -set xilinx_nonclocks /w:* /t:BUFGP %%x:+BUFGP[I] %%d\n"); - log(" iopadmap -outpad OBUF I:O -inpad IBUF O:I @xilinx_nonclocks\n"); + log(" iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I @xilinx_nonclocks\n"); log("\n"); log(" edif:\n"); log(" write_edif synth.edif\n"); @@ -171,8 +170,7 @@ struct SynthXilinxPass : public Pass { if (check_label(active, run_from, run_to, "fine")) { - Pass::call(design, "techmap"); - Pass::call(design, "opt -fast -full"); + Pass::call(design, "synth -run fine"); } if (check_label(active, run_from, run_to, "map_luts")) @@ -196,13 +194,13 @@ struct SynthXilinxPass : public Pass { if (check_label(active, run_from, run_to, "clkbuf")) { Pass::call(design, stringf("select -set xilinx_clocks %s/t:FDRE %%x:+FDRE[C] %s/t:FDRE %%d", top_module.c_str(), top_module.c_str())); - Pass::call(design, "iopadmap -inpad BUFGP O:I @xilinx_clocks"); + Pass::call(design, "iopadmap -bits -inpad BUFGP O:I @xilinx_clocks"); } if (check_label(active, run_from, run_to, "iobuf")) { Pass::call(design, stringf("select -set xilinx_nonclocks %s/w:* %s/t:BUFGP %%x:+BUFGP[I] %%d", top_module.c_str(), top_module.c_str())); - Pass::call(design, "iopadmap -outpad OBUF I:O -inpad IBUF O:I @xilinx_nonclocks"); + Pass::call(design, "iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I @xilinx_nonclocks"); } if (check_label(active, run_from, run_to, "edif")) From 947492867238d47c014189a0de2d49f3e5d9bbbc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Jan 2015 15:26:33 +0100 Subject: [PATCH 271/492] Towards Xilinx bram support --- passes/memory/memory_bram.cc | 1 - techlibs/xilinx/brams.txt | 49 +++++----- techlibs/xilinx/brams.v | 152 +++++++++++++++++++++++++++++++ techlibs/xilinx/tests/bram1.sh | 2 + techlibs/xilinx/tests/bram1_tb.v | 2 +- 5 files changed, 178 insertions(+), 28 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index fd5db188e..c2e320658 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -87,7 +87,6 @@ struct rules_t tokens.clear(); string line; while (std::getline(infile, line)) { - log("> %s\n", line.c_str()); for (string tok = next_token(line); !tok.empty(); tok = next_token(line)) { if (tok[0] == '#') break; diff --git a/techlibs/xilinx/brams.txt b/techlibs/xilinx/brams.txt index 69214fd59..0d039d78d 100644 --- a/techlibs/xilinx/brams.txt +++ b/techlibs/xilinx/brams.txt @@ -11,7 +11,7 @@ bram $__XILINX_RAMB36_SDP72 clkpol 2 3 endbram -bram $__XILINX_RAMB36_SDP36 +bram $__XILINX_RAMB18_SDP36 abits 10 dbits 36 groups 2 @@ -23,7 +23,7 @@ bram $__XILINX_RAMB36_SDP36 clkpol 2 3 endbram -bram $__XILINX_RAMB36_SDP18 +bram $__XILINX_RAMB18_TDP18 abits 11 dbits 18 groups 2 @@ -35,7 +35,7 @@ bram $__XILINX_RAMB36_SDP18 clkpol 2 3 endbram -bram $__XILINX_RAMB36_SDP9 +bram $__XILINX_RAMB18_TDP9 abits 12 dbits 9 groups 2 @@ -47,7 +47,7 @@ bram $__XILINX_RAMB36_SDP9 clkpol 2 3 endbram -bram $__XILINX_RAMB36_SDP4 +bram $__XILINX_RAMB18_TDP4 abits 13 dbits 4 groups 2 @@ -59,7 +59,7 @@ bram $__XILINX_RAMB36_SDP4 clkpol 2 3 endbram -bram $__XILINX_RAMB36_SDP2 +bram $__XILINX_RAMB18_TDP2 abits 14 dbits 2 groups 2 @@ -71,7 +71,7 @@ bram $__XILINX_RAMB36_SDP2 clkpol 2 3 endbram -bram $__XILINX_RAMB36_SDP1 +bram $__XILINX_RAMB18_TDP1 abits 15 dbits 1 groups 2 @@ -84,39 +84,36 @@ bram $__XILINX_RAMB36_SDP1 endbram match $__XILINX_RAMB36_SDP72 + min bits 4096 + min efficiency 5 shuffle_enable 8 - # min efficiency 20 + or_next_if_better +endmatch + +match $__XILINX_RAMB18_SDP36 + min bits 4096 + min efficiency 5 + shuffle_enable 4 # or_next_if_better endmatch -# match $__XILINX_RAMB36_SDP36 -# shuffle_enable 4 -# min efficiency 20 -# or_next_if_better -# endmatch -# -# match $__XILINX_RAMB36_SDP18 +# match $__XILINX_RAMB18_TDP18 # shuffle_enable 2 -# min efficiency 20 +# or_next_if_better +# endmatch +# +# match $__XILINX_RAMB18_TDP9 # or_next_if_better # endmatch # -# match $__XILINX_RAMB36_SDP9 -# min efficiency 20 +# match $__XILINX_RAMB18_TDP4 # or_next_if_better # endmatch # -# match $__XILINX_RAMB36_SDP4 -# min efficiency 20 +# match $__XILINX_RAMB18_TDP2 # or_next_if_better # endmatch # -# match $__XILINX_RAMB36_SDP2 -# min efficiency 20 -# or_next_if_better -# endmatch -# -# match $__XILINX_RAMB36_SDP1 -# min efficiency 20 +# match $__XILINX_RAMB18_TDP1 # endmatch diff --git a/techlibs/xilinx/brams.v b/techlibs/xilinx/brams.v index f98625bfa..a5d2b59cc 100644 --- a/techlibs/xilinx/brams.v +++ b/techlibs/xilinx/brams.v @@ -79,3 +79,155 @@ module \$__XILINX_RAMB36_SDP72 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .WEBWE(B1EN) ); endmodule + +// ------------------------------------------------------------------------ + +module \$__XILINX_RAMB18_SDP36 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); + parameter TRANSP2 = 1; + parameter CLKPOL2 = 1; + parameter CLKPOL3 = 1; + + input CLK2; + input CLK3; + + input [8:0] A1ADDR; + output [35:0] A1DATA; + + input [8:0] B1ADDR; + input [35:0] B1DATA; + input [3:0] B1EN; + + wire [15:0] A1ADDR_16 = {A1ADDR, 5'b0}; + wire [15:0] B1ADDR_16 = {B1ADDR, 5'b0}; + + wire [3:0] DIP, DOP; + wire [31:0] DI, DO; + + wire [35:0] A1DATA_BUF; + reg [35:0] B1DATA_Q; + reg [3:0] transparent_cycle; + + wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast"; + + generate if (CLKPOL2) + always @(posedge CLK2) begin transparent_cycle <= TRANSP2 && A1ADDR == B1ADDR ? B1EN : 0; B1DATA_Q <= B1DATA; end + else + always @(negedge CLK2) begin transparent_cycle <= TRANSP2 && A1ADDR == B1ADDR ? B1EN : 0; B1DATA_Q <= B1DATA; end + endgenerate + + assign A1DATA[ 8: 0] = transparent_cycle[0] ? B1DATA_Q[ 8: 0] : A1DATA_BUF[ 8: 0]; + assign A1DATA[17: 9] = transparent_cycle[1] ? B1DATA_Q[17: 9] : A1DATA_BUF[17: 9]; + assign A1DATA[26:18] = transparent_cycle[2] ? B1DATA_Q[26:18] : A1DATA_BUF[26:18]; + assign A1DATA[35:27] = transparent_cycle[3] ? B1DATA_Q[35:27] : A1DATA_BUF[35:27]; + + assign A1DATA_BUF = { DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; + assign { DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; + + RAMB18E1 #( + .RAM_MODE("SDP"), + .READ_WIDTH_A(36), + .WRITE_WIDTH_B(36), + .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"), + .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") + ) _TECHMAP_REPLACE_ ( + .DOBDO(DO[31:16]), + .DOADO(DO[15:0]), + .DOPBDOP(DOP[3:2]), + .DOPADOP(DOP[1:0]), + .DIBDI(DI[31:16]), + .DIADI(DI[15:0]), + .DIPBDIP(DIP[3:2]), + .DIPADIP(DIP[1:0]), + + .ADDRARDADDR(A1ADDR_16), + .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), + .ENARDEN(|1), + .REGCEAREGCE(|1), + .RSTRAMARSTRAM(|0), + .RSTREGARSTREG(|0), + .WEA(4'b0), + + .ADDRBWRADDR(B1ADDR_16), + .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), + .ENBWREN(|1), + .REGCEB(|0), + .RSTRAMB(|0), + .RSTREGB(|0), + .WEBWE(B1EN) + ); +endmodule + +// ------------------------------------------------------------------------ + +module \$__XILINX_RAMB18_TDP18 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); + parameter TRANSP2 = 1; + parameter CLKPOL2 = 1; + parameter CLKPOL3 = 1; + + input CLK2; + input CLK3; + + input [8:0] A1ADDR; + output [17:0] A1DATA; + + input [8:0] B1ADDR; + input [17:0] B1DATA; + input [1:0] B1EN; + + wire [13:0] A1ADDR_14 = {A1ADDR, 4'b0}; + wire [13:0] B1ADDR_14 = {B1ADDR, 4'b0}; + + wire [1:0] DIP, DOP; + wire [15:0] DI, DO; + + wire [17:0] A1DATA_BUF; + reg [17:0] B1DATA_Q; + reg [1:0] transparent_cycle; + + wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast"; + + generate if (CLKPOL2) + always @(posedge CLK2) begin transparent_cycle <= TRANSP2 && A1ADDR == B1ADDR ? B1EN : 0; B1DATA_Q <= B1DATA; end + else + always @(negedge CLK2) begin transparent_cycle <= TRANSP2 && A1ADDR == B1ADDR ? B1EN : 0; B1DATA_Q <= B1DATA; end + endgenerate + + assign A1DATA[ 8: 0] = transparent_cycle[0] ? B1DATA_Q[ 8: 0] : A1DATA_BUF[ 8: 0]; + assign A1DATA[17: 9] = transparent_cycle[1] ? B1DATA_Q[17: 9] : A1DATA_BUF[17: 9]; + + assign A1DATA_BUF = { DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; + assign { DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; + + RAMB18E1 #( + .RAM_MODE("TDP"), + .READ_WIDTH_A(18), + .READ_WIDTH_B(18), + .WRITE_WIDTH_A(18), + .WRITE_WIDTH_B(18), + .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"), + .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") + ) _TECHMAP_REPLACE_ ( + .DIADI(16'b0), + .DIPADIP(2'b0), + .DOADO(DO[15:0]), + .DOPADOP(DOP[1:0]), + .ADDRARDADDR(A1ADDR_14), + .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), + .ENARDEN(|1), + .REGCEAREGCE(|1), + .RSTRAMARSTRAM(|0), + .RSTREGARSTREG(|0), + .WEA(2'b0), + + .DIBDI(DI[15:0]), + .DIPBDIP(DIP[1:0]), + .ADDRBWRADDR(B1ADDR_14), + .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), + .ENBWREN(|1), + .REGCEB(|0), + .RSTRAMB(|0), + .RSTREGB(|0), + .WEBWE({2'b00, B1EN}) + ); +endmodule + diff --git a/techlibs/xilinx/tests/bram1.sh b/techlibs/xilinx/tests/bram1.sh index f233be9fa..15c4034aa 100644 --- a/techlibs/xilinx/tests/bram1.sh +++ b/techlibs/xilinx/tests/bram1.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -e + use_xsim=false unisims=/opt/Xilinx/Vivado/2014.4/data/verilog/src/unisims diff --git a/techlibs/xilinx/tests/bram1_tb.v b/techlibs/xilinx/tests/bram1_tb.v index c14cf6e30..dbefdb6e8 100644 --- a/techlibs/xilinx/tests/bram1_tb.v +++ b/techlibs/xilinx/tests/bram1_tb.v @@ -70,7 +70,7 @@ module bram1_tb #( expected_rd[j] = RD_DATA[j]; end - $display("#OUT# | WA=%x WD=%x WE=%x | RA=%x RD=%x | %s", WR_ADDR, WR_DATA, WR_EN, RD_ADDR, RD_DATA, expected_rd === RD_DATA ? "ok" : "ERROR"); + $display("#OUT# %3d | WA=%x WD=%x WE=%x | RA=%x RD=%x | %s", i, WR_ADDR, WR_DATA, WR_EN, RD_ADDR, RD_DATA, expected_rd === RD_DATA ? "ok" : "ERROR"); if (expected_rd !== RD_DATA) begin -> error; error_ind = ~error_ind; end end end From 9fb715dc74b632c74aafec1652d4e66dc28cc341 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Jan 2015 15:46:58 +0100 Subject: [PATCH 272/492] build fix for mxe --- kernel/driver.cc | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index 2cbdba8f3..1698e216c 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -409,21 +409,22 @@ int main(int argc, char **argv) #ifdef YOSYS_ENABLE_COVER if (getenv("YOSYS_COVER_DIR") || getenv("YOSYS_COVER_FILE")) { - char filename_buffer[4096]; + string filename; FILE *f; if (getenv("YOSYS_COVER_DIR")) { - snprintf(filename_buffer, 4096, "%s/yosys_cover_%d_XXXXXX.txt", getenv("YOSYS_COVER_DIR"), getpid()); - f = fdopen(mkstemps(filename_buffer, 4), "w"); + filename = stringf("%s/yosys_cover_%d_XXXXXX.txt", getenv("YOSYS_COVER_DIR"), getpid()); + filename = make_temp_file(filename); } else { - snprintf(filename_buffer, 4096, "%s", getenv("YOSYS_COVER_FILE")); - f = fopen(filename_buffer, "a+"); + filename = getenv("YOSYS_COVER_FILE"); } - if (f == NULL) - log_error("Can't create coverage file `%s'.\n", filename_buffer); + f = fopen(filename.c_str(), "a+"); - log("\n", filename_buffer); + if (f == NULL) + log_error("Can't create coverage file `%s'.\n", filename.c_str()); + + log("\n", filename.c_str()); for (auto &it : get_coverage_data()) fprintf(f, "%-60s %10d %s\n", it.second.first.c_str(), it.second.second, it.first.c_str()); From 859e3e41e7c96e2442d5ff2d3fb54dc5bdffea94 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Jan 2015 16:05:00 +0100 Subject: [PATCH 273/492] hashlib iterator fix --- kernel/hashlib.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 5e00e89d6..72e9bc2ef 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -287,7 +287,7 @@ class dict } public: - class const_iterator + class const_iterator : public std::iterator> { friend class dict; protected: @@ -304,7 +304,7 @@ public: const std::pair *operator->() const { return &ptr->entries[index].udata; } }; - class iterator + class iterator : public std::iterator> { friend class dict; protected: @@ -609,7 +609,7 @@ class pool } public: - class const_iterator + class const_iterator : public std::iterator { friend class pool; protected: @@ -625,7 +625,7 @@ public: const K *operator->() const { return &ptr->entries[index].udata; } }; - class iterator + class iterator : public std::iterator { friend class pool; protected: From da7205010771f4dd0db6ffa9ff4e373a2a03588d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Jan 2015 16:08:04 +0100 Subject: [PATCH 274/492] removed old debug code --- passes/memory/memory_bram.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index c2e320658..8c7338b91 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -436,7 +436,6 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ sig_en.append(last_en_bit); } if (last_en_bit != wr_en[i + cell_port_i*mem_width]) { - log_dump(last_en_bit, wr_en[i + cell_port_i*mem_width]); log(" Bram port %c%d has incompatible enable structure.\n", pi.group + 'A', pi.index + 1); goto skip_bram_wport; } From 07703bdac40f5b7807b627d289e67897bf2b7396 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Jan 2015 16:12:43 +0100 Subject: [PATCH 275/492] fixed compiler warning on non-linux archs --- kernel/log.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/log.cc b/kernel/log.cc index 2be425ffd..70bff8f5b 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -253,9 +253,9 @@ void log_pop() log_flush(); } +#ifdef __linux__ void log_backtrace(const char *prefix, int levels) { -#ifdef __linux__ if (levels <= 0) return; Dl_info dli; @@ -341,8 +341,10 @@ void log_backtrace(const char *prefix, int levels) } if (levels <= 9) return; -#endif } +#else +void log_backtrace(const char*, int) { } +#endif void log_reset_stack() { From 7cc5192125244d3fd990f3043d619262066ff962 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Jan 2015 17:21:18 +0100 Subject: [PATCH 276/492] small fix in xilinx/brams.v --- techlibs/xilinx/brams.v | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/brams.v b/techlibs/xilinx/brams.v index a5d2b59cc..a0baeaf04 100644 --- a/techlibs/xilinx/brams.v +++ b/techlibs/xilinx/brams.v @@ -97,8 +97,8 @@ module \$__XILINX_RAMB18_SDP36 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN input [35:0] B1DATA; input [3:0] B1EN; - wire [15:0] A1ADDR_16 = {A1ADDR, 5'b0}; - wire [15:0] B1ADDR_16 = {B1ADDR, 5'b0}; + wire [13:0] A1ADDR_14 = {A1ADDR, 5'b0}; + wire [13:0] B1ADDR_14 = {B1ADDR, 5'b0}; wire [3:0] DIP, DOP; wire [31:0] DI, DO; @@ -139,15 +139,15 @@ module \$__XILINX_RAMB18_SDP36 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .DIPBDIP(DIP[3:2]), .DIPADIP(DIP[1:0]), - .ADDRARDADDR(A1ADDR_16), + .ADDRARDADDR(A1ADDR_14), .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), .ENARDEN(|1), .REGCEAREGCE(|1), .RSTRAMARSTRAM(|0), .RSTREGARSTREG(|0), - .WEA(4'b0), + .WEA(2'b0), - .ADDRBWRADDR(B1ADDR_16), + .ADDRBWRADDR(B1ADDR_14), .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), .ENBWREN(|1), .REGCEB(|0), From ec2eef89fab03beb655f4fe3a16b002d3bf439f7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Jan 2015 23:21:52 +0100 Subject: [PATCH 277/492] Towards Xilinx bram support --- techlibs/xilinx/brams.txt | 26 +++++++------- techlibs/xilinx/brams.v | 4 +-- techlibs/xilinx/tests/bram1_tb.v | 59 ++++++++++++++++++++++++++------ 3 files changed, 65 insertions(+), 24 deletions(-) diff --git a/techlibs/xilinx/brams.txt b/techlibs/xilinx/brams.txt index 0d039d78d..59af1bc51 100644 --- a/techlibs/xilinx/brams.txt +++ b/techlibs/xilinx/brams.txt @@ -12,7 +12,7 @@ bram $__XILINX_RAMB36_SDP72 endbram bram $__XILINX_RAMB18_SDP36 - abits 10 + abits 9 dbits 36 groups 2 ports 1 1 @@ -24,7 +24,7 @@ bram $__XILINX_RAMB18_SDP36 endbram bram $__XILINX_RAMB18_TDP18 - abits 11 + abits 10 dbits 18 groups 2 ports 1 1 @@ -36,7 +36,7 @@ bram $__XILINX_RAMB18_TDP18 endbram bram $__XILINX_RAMB18_TDP9 - abits 12 + abits 11 dbits 9 groups 2 ports 1 1 @@ -48,7 +48,7 @@ bram $__XILINX_RAMB18_TDP9 endbram bram $__XILINX_RAMB18_TDP4 - abits 13 + abits 12 dbits 4 groups 2 ports 1 1 @@ -60,7 +60,7 @@ bram $__XILINX_RAMB18_TDP4 endbram bram $__XILINX_RAMB18_TDP2 - abits 14 + abits 13 dbits 2 groups 2 ports 1 1 @@ -72,7 +72,7 @@ bram $__XILINX_RAMB18_TDP2 endbram bram $__XILINX_RAMB18_TDP1 - abits 15 + abits 14 dbits 1 groups 2 ports 1 1 @@ -94,14 +94,16 @@ match $__XILINX_RAMB18_SDP36 min bits 4096 min efficiency 5 shuffle_enable 4 - # or_next_if_better + or_next_if_better endmatch -# match $__XILINX_RAMB18_TDP18 -# shuffle_enable 2 -# or_next_if_better -# endmatch -# +match $__XILINX_RAMB18_TDP18 + min bits 4096 + min efficiency 5 + shuffle_enable 2 + # or_next_if_better +endmatch + # match $__XILINX_RAMB18_TDP9 # or_next_if_better # endmatch diff --git a/techlibs/xilinx/brams.v b/techlibs/xilinx/brams.v index a0baeaf04..a2724fe37 100644 --- a/techlibs/xilinx/brams.v +++ b/techlibs/xilinx/brams.v @@ -167,10 +167,10 @@ module \$__XILINX_RAMB18_TDP18 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN input CLK2; input CLK3; - input [8:0] A1ADDR; + input [9:0] A1ADDR; output [17:0] A1DATA; - input [8:0] B1ADDR; + input [9:0] B1ADDR; input [17:0] B1DATA; input [1:0] B1EN; diff --git a/techlibs/xilinx/tests/bram1_tb.v b/techlibs/xilinx/tests/bram1_tb.v index dbefdb6e8..ff0929dab 100644 --- a/techlibs/xilinx/tests/bram1_tb.v +++ b/techlibs/xilinx/tests/bram1_tb.v @@ -21,6 +21,21 @@ module bram1_tb #( .RD_DATA(RD_DATA) ); + reg [63:0] xorshift64_state = 64'd88172645463325252; + + task xorshift64_next; + begin + // see page 4 of Marsaglia, George (July 2003). "Xorshift RNGs". Journal of Statistical Software 8 (14). + xorshift64_state = xorshift64_state ^ (xorshift64_state << 13); + xorshift64_state = xorshift64_state ^ (xorshift64_state >> 7); + xorshift64_state = xorshift64_state ^ (xorshift64_state << 17); + end + endtask + + reg [ABITS-1:0] randaddr1; + reg [ABITS-1:0] randaddr2; + reg [ABITS-1:0] randaddr3; + function [31:0] getaddr(input [3:0] n); begin case (n) @@ -31,14 +46,19 @@ module bram1_tb #( 4: getaddr = 'b11011 << (ABITS / 4); 5: getaddr = 'b11011 << (2*ABITS / 4); 6: getaddr = 'b11011 << (3*ABITS / 4); - 7: getaddr = 123456789; - default: getaddr = 1 << (2*n-16); + 7: getaddr = randaddr1; + 8: getaddr = randaddr2; + 9: getaddr = randaddr3; + default: begin + getaddr = 1 << (2*n-16); + if (!getaddr) getaddr = xorshift64_state; + end endcase end endfunction reg [DBITS-1:0] memory [0:2**ABITS-1]; - reg [DBITS-1:0] expected_rd; + reg [DBITS-1:0] expected_rd, expected_rd_masked; event error; reg error_ind = 0; @@ -47,12 +67,33 @@ module bram1_tb #( initial begin // $dumpfile("testbench.vcd"); // $dumpvars(0, bram1_tb); + + xorshift64_next; + xorshift64_next; + xorshift64_next; + xorshift64_next; + + randaddr1 = xorshift64_state; + xorshift64_next; + + randaddr2 = xorshift64_state; + xorshift64_next; + + randaddr3 = xorshift64_state; + xorshift64_next; + clk <= 0; for (i = 0; i < 256; i = i+1) begin - WR_DATA <= i; + if (DBITS > 64) + WR_DATA <= (xorshift64_state << (DBITS-64)) ^ xorshift64_state; + else + WR_DATA <= xorshift64_state; + xorshift64_next; WR_ADDR <= getaddr(i[7:4]); + xorshift64_next; RD_ADDR <= getaddr(i[3:0]); WR_EN <= ^i; + xorshift64_next; #1; clk <= 1; #1; clk <= 0; @@ -65,13 +106,11 @@ module bram1_tb #( if (WR_EN) memory[WR_ADDR] = WR_DATA; end - for (j = 0; j < DBITS; j = j+1) begin - if (expected_rd[j] === 1'bx) - expected_rd[j] = RD_DATA[j]; - end + for (j = 0; j < DBITS; j = j+1) + expected_rd_masked[j] = expected_rd[j] !== 1'bx ? expected_rd[j] : RD_DATA[j]; - $display("#OUT# %3d | WA=%x WD=%x WE=%x | RA=%x RD=%x | %s", i, WR_ADDR, WR_DATA, WR_EN, RD_ADDR, RD_DATA, expected_rd === RD_DATA ? "ok" : "ERROR"); - if (expected_rd !== RD_DATA) begin -> error; error_ind = ~error_ind; end + $display("#OUT# %3d | WA=%x WD=%x WE=%x | RA=%x RD=%x (%x) | %s", i, WR_ADDR, WR_DATA, WR_EN, RD_ADDR, RD_DATA, expected_rd, expected_rd_masked === RD_DATA ? "ok" : "ERROR"); + if (expected_rd_masked !== RD_DATA) begin -> error; error_ind = ~error_ind; end end end endmodule From 08c13f635cb59f701b51a14caf608c503b6eecb1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Jan 2015 23:54:33 +0100 Subject: [PATCH 278/492] Xilinx RAMB36/RAMB18 memory_bram support complete --- techlibs/xilinx/brams.txt | 42 +++-- techlibs/xilinx/brams.v | 292 +++++++++++++++++++++++++++++++ techlibs/xilinx/tests/bram1_tb.v | 2 +- 3 files changed, 320 insertions(+), 16 deletions(-) diff --git a/techlibs/xilinx/brams.txt b/techlibs/xilinx/brams.txt index 59af1bc51..46a6ab49e 100644 --- a/techlibs/xilinx/brams.txt +++ b/techlibs/xilinx/brams.txt @@ -101,21 +101,33 @@ match $__XILINX_RAMB18_TDP18 min bits 4096 min efficiency 5 shuffle_enable 2 - # or_next_if_better + or_next_if_better endmatch -# match $__XILINX_RAMB18_TDP9 -# or_next_if_better -# endmatch -# -# match $__XILINX_RAMB18_TDP4 -# or_next_if_better -# endmatch -# -# match $__XILINX_RAMB18_TDP2 -# or_next_if_better -# endmatch -# -# match $__XILINX_RAMB18_TDP1 -# endmatch +match $__XILINX_RAMB18_TDP9 + min bits 4096 + min efficiency 5 + shuffle_enable 2 + or_next_if_better +endmatch + +match $__XILINX_RAMB18_TDP4 + min bits 4096 + min efficiency 5 + shuffle_enable 2 + or_next_if_better +endmatch + +match $__XILINX_RAMB18_TDP2 + min bits 4096 + min efficiency 5 + shuffle_enable 2 + or_next_if_better +endmatch + +match $__XILINX_RAMB18_TDP1 + min bits 4096 + min efficiency 5 + shuffle_enable 2 +endmatch diff --git a/techlibs/xilinx/brams.v b/techlibs/xilinx/brams.v index a2724fe37..cfa598bce 100644 --- a/techlibs/xilinx/brams.v +++ b/techlibs/xilinx/brams.v @@ -231,3 +231,295 @@ module \$__XILINX_RAMB18_TDP18 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN ); endmodule +// ------------------------------------------------------------------------ + +module \$__XILINX_RAMB18_TDP9 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); + parameter TRANSP2 = 1; + parameter CLKPOL2 = 1; + parameter CLKPOL3 = 1; + + input CLK2; + input CLK3; + + input [10:0] A1ADDR; + output [8:0] A1DATA; + + input [10:0] B1ADDR; + input [8:0] B1DATA; + input B1EN; + + wire [13:0] A1ADDR_14 = {A1ADDR, 3'b0}; + wire [13:0] B1ADDR_14 = {B1ADDR, 3'b0}; + + wire DIP, DOP; + wire [7:0] DI, DO; + + wire [8:0] A1DATA_BUF; + reg [8:0] B1DATA_Q; + reg transparent_cycle; + + wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast"; + + generate if (CLKPOL2) + always @(posedge CLK2) begin transparent_cycle <= TRANSP2 && A1ADDR == B1ADDR ? B1EN : 0; B1DATA_Q <= B1DATA; end + else + always @(negedge CLK2) begin transparent_cycle <= TRANSP2 && A1ADDR == B1ADDR ? B1EN : 0; B1DATA_Q <= B1DATA; end + endgenerate + + assign A1DATA = transparent_cycle ? B1DATA_Q : A1DATA_BUF; + + assign A1DATA_BUF = { DOP, DO }; + assign { DIP, DI } = B1DATA; + + RAMB18E1 #( + .RAM_MODE("TDP"), + .READ_WIDTH_A(9), + .READ_WIDTH_B(9), + .WRITE_WIDTH_A(9), + .WRITE_WIDTH_B(9), + .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"), + .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") + ) _TECHMAP_REPLACE_ ( + .DIADI(16'b0), + .DIPADIP(2'b0), + .DOADO(DO[7:0]), + .DOPADOP(DOP), + .ADDRARDADDR(A1ADDR_14), + .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), + .ENARDEN(|1), + .REGCEAREGCE(|1), + .RSTRAMARSTRAM(|0), + .RSTREGARSTREG(|0), + .WEA(2'b0), + + .DIBDI({8'b0, DI}), + .DIPBDIP({1'b0, DIP}), + .ADDRBWRADDR(B1ADDR_14), + .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), + .ENBWREN(|1), + .REGCEB(|0), + .RSTRAMB(|0), + .RSTREGB(|0), + .WEBWE({3'b00, B1EN}) + ); +endmodule + +// ------------------------------------------------------------------------ + +module \$__XILINX_RAMB18_TDP4 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); + parameter TRANSP2 = 1; + parameter CLKPOL2 = 1; + parameter CLKPOL3 = 1; + + input CLK2; + input CLK3; + + input [11:0] A1ADDR; + output [3:0] A1DATA; + + input [11:0] B1ADDR; + input [3:0] B1DATA; + input B1EN; + + wire [13:0] A1ADDR_14 = {A1ADDR, 2'b0}; + wire [13:0] B1ADDR_14 = {B1ADDR, 2'b0}; + + wire DIP, DOP; + wire [7:0] DI, DO; + + wire [3:0] A1DATA_BUF; + reg [3:0] B1DATA_Q; + reg transparent_cycle; + + wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast"; + + generate if (CLKPOL2) + always @(posedge CLK2) begin transparent_cycle <= TRANSP2 && A1ADDR == B1ADDR ? B1EN : 0; B1DATA_Q <= B1DATA; end + else + always @(negedge CLK2) begin transparent_cycle <= TRANSP2 && A1ADDR == B1ADDR ? B1EN : 0; B1DATA_Q <= B1DATA; end + endgenerate + + assign A1DATA = transparent_cycle ? B1DATA_Q : A1DATA_BUF; + + assign A1DATA_BUF = { DOP, DO }; + assign { DIP, DI } = B1DATA; + + RAMB18E1 #( + .RAM_MODE("TDP"), + .READ_WIDTH_A(4), + .READ_WIDTH_B(4), + .WRITE_WIDTH_A(4), + .WRITE_WIDTH_B(4), + .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"), + .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") + ) _TECHMAP_REPLACE_ ( + .DIADI(16'b0), + .DIPADIP(2'b0), + .DOADO(DO[7:0]), + .DOPADOP(DOP), + .ADDRARDADDR(A1ADDR_14), + .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), + .ENARDEN(|1), + .REGCEAREGCE(|1), + .RSTRAMARSTRAM(|0), + .RSTREGARSTREG(|0), + .WEA(2'b0), + + .DIBDI({8'b0, DI}), + .DIPBDIP({1'b0, DIP}), + .ADDRBWRADDR(B1ADDR_14), + .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), + .ENBWREN(|1), + .REGCEB(|0), + .RSTRAMB(|0), + .RSTREGB(|0), + .WEBWE({3'b00, B1EN}) + ); +endmodule + +// ------------------------------------------------------------------------ + +module \$__XILINX_RAMB18_TDP2 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); + parameter TRANSP2 = 1; + parameter CLKPOL2 = 1; + parameter CLKPOL3 = 1; + + input CLK2; + input CLK3; + + input [12:0] A1ADDR; + output [1:0] A1DATA; + + input [12:0] B1ADDR; + input [1:0] B1DATA; + input B1EN; + + wire [13:0] A1ADDR_14 = {A1ADDR, 1'b0}; + wire [13:0] B1ADDR_14 = {B1ADDR, 1'b0}; + + wire DIP, DOP; + wire [7:0] DI, DO; + + wire [3:0] A1DATA_BUF; + reg [3:0] B1DATA_Q; + reg transparent_cycle; + + wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast"; + + generate if (CLKPOL2) + always @(posedge CLK2) begin transparent_cycle <= TRANSP2 && A1ADDR == B1ADDR ? B1EN : 0; B1DATA_Q <= B1DATA; end + else + always @(negedge CLK2) begin transparent_cycle <= TRANSP2 && A1ADDR == B1ADDR ? B1EN : 0; B1DATA_Q <= B1DATA; end + endgenerate + + assign A1DATA = transparent_cycle ? B1DATA_Q : A1DATA_BUF; + + assign A1DATA_BUF = { DOP, DO }; + assign { DIP, DI } = B1DATA; + + RAMB18E1 #( + .RAM_MODE("TDP"), + .READ_WIDTH_A(2), + .READ_WIDTH_B(2), + .WRITE_WIDTH_A(2), + .WRITE_WIDTH_B(2), + .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"), + .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") + ) _TECHMAP_REPLACE_ ( + .DIADI(16'b0), + .DIPADIP(2'b0), + .DOADO(DO[7:0]), + .DOPADOP(DOP), + .ADDRARDADDR(A1ADDR_14), + .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), + .ENARDEN(|1), + .REGCEAREGCE(|1), + .RSTRAMARSTRAM(|0), + .RSTREGARSTREG(|0), + .WEA(2'b0), + + .DIBDI({8'b0, DI}), + .DIPBDIP({1'b0, DIP}), + .ADDRBWRADDR(B1ADDR_14), + .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), + .ENBWREN(|1), + .REGCEB(|0), + .RSTRAMB(|0), + .RSTREGB(|0), + .WEBWE({3'b00, B1EN}) + ); +endmodule + +// ------------------------------------------------------------------------ + +module \$__XILINX_RAMB18_TDP1 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN); + parameter TRANSP2 = 1; + parameter CLKPOL2 = 1; + parameter CLKPOL3 = 1; + + input CLK2; + input CLK3; + + input [13:0] A1ADDR; + output A1DATA; + + input [13:0] B1ADDR; + input B1DATA; + input B1EN; + + wire [13:0] A1ADDR_14 = A1ADDR; + wire [13:0] B1ADDR_14 = B1ADDR; + + wire DIP, DOP; + wire [7:0] DI, DO; + + wire [3:0] A1DATA_BUF; + reg [3:0] B1DATA_Q; + reg transparent_cycle; + + wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast"; + + generate if (CLKPOL2) + always @(posedge CLK2) begin transparent_cycle <= TRANSP2 && A1ADDR == B1ADDR ? B1EN : 0; B1DATA_Q <= B1DATA; end + else + always @(negedge CLK2) begin transparent_cycle <= TRANSP2 && A1ADDR == B1ADDR ? B1EN : 0; B1DATA_Q <= B1DATA; end + endgenerate + + assign A1DATA = transparent_cycle ? B1DATA_Q : A1DATA_BUF; + + assign A1DATA_BUF = { DOP, DO }; + assign { DIP, DI } = B1DATA; + + RAMB18E1 #( + .RAM_MODE("TDP"), + .READ_WIDTH_A(1), + .READ_WIDTH_B(1), + .WRITE_WIDTH_A(1), + .WRITE_WIDTH_B(1), + .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"), + .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") + ) _TECHMAP_REPLACE_ ( + .DIADI(16'b0), + .DIPADIP(2'b0), + .DOADO(DO[7:0]), + .DOPADOP(DOP), + .ADDRARDADDR(A1ADDR_14), + .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), + .ENARDEN(|1), + .REGCEAREGCE(|1), + .RSTRAMARSTRAM(|0), + .RSTREGARSTREG(|0), + .WEA(2'b0), + + .DIBDI({8'b0, DI}), + .DIPBDIP({1'b0, DIP}), + .ADDRBWRADDR(B1ADDR_14), + .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), + .ENBWREN(|1), + .REGCEB(|0), + .RSTRAMB(|0), + .RSTREGB(|0), + .WEBWE({3'b00, B1EN}) + ); +endmodule + diff --git a/techlibs/xilinx/tests/bram1_tb.v b/techlibs/xilinx/tests/bram1_tb.v index ff0929dab..6ed04d4ad 100644 --- a/techlibs/xilinx/tests/bram1_tb.v +++ b/techlibs/xilinx/tests/bram1_tb.v @@ -21,7 +21,7 @@ module bram1_tb #( .RD_DATA(RD_DATA) ); - reg [63:0] xorshift64_state = 64'd88172645463325252; + reg [63:0] xorshift64_state = 64'd88172645463325252 ^ (ABITS << 24) ^ (DBITS << 16) ^ (TRANSP << 8); task xorshift64_next; begin From b26590f8ab2bc77b6209a98240d465af7d3ee266 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Jan 2015 23:59:53 +0100 Subject: [PATCH 279/492] memory_bram hotfix for memories with width 1 --- passes/memory/memory_bram.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 8c7338b91..b212e92ed 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -294,10 +294,10 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ SigSpec rd_data = cell->getPort("\\RD_DATA"); SigSpec rd_addr = cell->getPort("\\RD_ADDR"); - if (match.shuffle_enable) + if (match.shuffle_enable && bram.dbits >= match.shuffle_enable*2) { int bucket_size = bram.dbits / match.shuffle_enable; - log(" Shuffle enable and data bit to accommodate enable buckets of size %d..\n", bucket_size); + log(" Shuffle bit order to accommodate enable buckets of size %d..\n", bucket_size); // extract unshuffled data/enable bits @@ -363,7 +363,7 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ } } - log(" Results of enable shuffling:"); + log(" Results of bit order shuffling:"); for (int v : shuffle_map) log(" %d", v); log("\n"); From 584c5f3937f11bcfc29eb9b206b941fbc2619b85 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 7 Jan 2015 01:28:18 +0100 Subject: [PATCH 280/492] Cleanups in xilinx bram descriptions --- techlibs/xilinx/brams.v | 64 ++++++++++++++++---------------- techlibs/xilinx/tests/bram1_tb.v | 8 ++-- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/techlibs/xilinx/brams.v b/techlibs/xilinx/brams.v index cfa598bce..83f2aede4 100644 --- a/techlibs/xilinx/brams.v +++ b/techlibs/xilinx/brams.v @@ -209,8 +209,8 @@ module \$__XILINX_RAMB18_TDP18 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), - .DOADO(DO[15:0]), - .DOPADOP(DOP[1:0]), + .DOADO(DO), + .DOPADOP(DOP), .ADDRARDADDR(A1ADDR_14), .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), .ENARDEN(|1), @@ -219,8 +219,8 @@ module \$__XILINX_RAMB18_TDP18 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .RSTREGARSTREG(|0), .WEA(2'b0), - .DIBDI(DI[15:0]), - .DIPBDIP(DIP[1:0]), + .DIBDI(DI), + .DIPBDIP(DIP), .ADDRBWRADDR(B1ADDR_14), .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), .ENBWREN(|1), @@ -251,8 +251,8 @@ module \$__XILINX_RAMB18_TDP9 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) wire [13:0] A1ADDR_14 = {A1ADDR, 3'b0}; wire [13:0] B1ADDR_14 = {B1ADDR, 3'b0}; - wire DIP, DOP; - wire [7:0] DI, DO; + wire [1:0] DIP, DOP; + wire [15:0] DI, DO; wire [8:0] A1DATA_BUF; reg [8:0] B1DATA_Q; @@ -268,8 +268,8 @@ module \$__XILINX_RAMB18_TDP9 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) assign A1DATA = transparent_cycle ? B1DATA_Q : A1DATA_BUF; - assign A1DATA_BUF = { DOP, DO }; - assign { DIP, DI } = B1DATA; + assign A1DATA_BUF = { DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; + assign { DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; RAMB18E1 #( .RAM_MODE("TDP"), @@ -282,7 +282,7 @@ module \$__XILINX_RAMB18_TDP9 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), - .DOADO(DO[7:0]), + .DOADO(DO), .DOPADOP(DOP), .ADDRARDADDR(A1ADDR_14), .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), @@ -292,8 +292,8 @@ module \$__XILINX_RAMB18_TDP9 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .RSTREGARSTREG(|0), .WEA(2'b0), - .DIBDI({8'b0, DI}), - .DIPBDIP({1'b0, DIP}), + .DIBDI(DI), + .DIPBDIP(DIP), .ADDRBWRADDR(B1ADDR_14), .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), .ENBWREN(|1), @@ -324,8 +324,8 @@ module \$__XILINX_RAMB18_TDP4 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) wire [13:0] A1ADDR_14 = {A1ADDR, 2'b0}; wire [13:0] B1ADDR_14 = {B1ADDR, 2'b0}; - wire DIP, DOP; - wire [7:0] DI, DO; + wire [1:0] DIP, DOP; + wire [15:0] DI, DO; wire [3:0] A1DATA_BUF; reg [3:0] B1DATA_Q; @@ -341,8 +341,8 @@ module \$__XILINX_RAMB18_TDP4 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) assign A1DATA = transparent_cycle ? B1DATA_Q : A1DATA_BUF; - assign A1DATA_BUF = { DOP, DO }; - assign { DIP, DI } = B1DATA; + assign A1DATA_BUF = { DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; + assign { DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; RAMB18E1 #( .RAM_MODE("TDP"), @@ -355,7 +355,7 @@ module \$__XILINX_RAMB18_TDP4 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), - .DOADO(DO[7:0]), + .DOADO(DO), .DOPADOP(DOP), .ADDRARDADDR(A1ADDR_14), .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), @@ -365,8 +365,8 @@ module \$__XILINX_RAMB18_TDP4 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .RSTREGARSTREG(|0), .WEA(2'b0), - .DIBDI({8'b0, DI}), - .DIPBDIP({1'b0, DIP}), + .DIBDI(DI), + .DIPBDIP(DIP), .ADDRBWRADDR(B1ADDR_14), .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), .ENBWREN(|1), @@ -397,8 +397,8 @@ module \$__XILINX_RAMB18_TDP2 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) wire [13:0] A1ADDR_14 = {A1ADDR, 1'b0}; wire [13:0] B1ADDR_14 = {B1ADDR, 1'b0}; - wire DIP, DOP; - wire [7:0] DI, DO; + wire [1:0] DIP, DOP; + wire [15:0] DI, DO; wire [3:0] A1DATA_BUF; reg [3:0] B1DATA_Q; @@ -414,8 +414,8 @@ module \$__XILINX_RAMB18_TDP2 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) assign A1DATA = transparent_cycle ? B1DATA_Q : A1DATA_BUF; - assign A1DATA_BUF = { DOP, DO }; - assign { DIP, DI } = B1DATA; + assign A1DATA_BUF = { DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; + assign { DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; RAMB18E1 #( .RAM_MODE("TDP"), @@ -428,7 +428,7 @@ module \$__XILINX_RAMB18_TDP2 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), - .DOADO(DO[7:0]), + .DOADO(DO), .DOPADOP(DOP), .ADDRARDADDR(A1ADDR_14), .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), @@ -438,8 +438,8 @@ module \$__XILINX_RAMB18_TDP2 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .RSTREGARSTREG(|0), .WEA(2'b0), - .DIBDI({8'b0, DI}), - .DIPBDIP({1'b0, DIP}), + .DIBDI(DI), + .DIPBDIP(DIP), .ADDRBWRADDR(B1ADDR_14), .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), .ENBWREN(|1), @@ -470,8 +470,8 @@ module \$__XILINX_RAMB18_TDP1 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) wire [13:0] A1ADDR_14 = A1ADDR; wire [13:0] B1ADDR_14 = B1ADDR; - wire DIP, DOP; - wire [7:0] DI, DO; + wire [1:0] DIP, DOP; + wire [15:0] DI, DO; wire [3:0] A1DATA_BUF; reg [3:0] B1DATA_Q; @@ -487,8 +487,8 @@ module \$__XILINX_RAMB18_TDP1 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) assign A1DATA = transparent_cycle ? B1DATA_Q : A1DATA_BUF; - assign A1DATA_BUF = { DOP, DO }; - assign { DIP, DI } = B1DATA; + assign A1DATA_BUF = { DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; + assign { DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; RAMB18E1 #( .RAM_MODE("TDP"), @@ -501,7 +501,7 @@ module \$__XILINX_RAMB18_TDP1 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), - .DOADO(DO[7:0]), + .DOADO(DO), .DOPADOP(DOP), .ADDRARDADDR(A1ADDR_14), .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), @@ -511,8 +511,8 @@ module \$__XILINX_RAMB18_TDP1 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .RSTREGARSTREG(|0), .WEA(2'b0), - .DIBDI({8'b0, DI}), - .DIPBDIP({1'b0, DIP}), + .DIBDI(DI), + .DIPBDIP(DIP), .ADDRBWRADDR(B1ADDR_14), .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), .ENBWREN(|1), diff --git a/techlibs/xilinx/tests/bram1_tb.v b/techlibs/xilinx/tests/bram1_tb.v index 6ed04d4ad..8f854b749 100644 --- a/techlibs/xilinx/tests/bram1_tb.v +++ b/techlibs/xilinx/tests/bram1_tb.v @@ -83,16 +83,16 @@ module bram1_tb #( xorshift64_next; clk <= 0; - for (i = 0; i < 256; i = i+1) begin + for (i = 0; i < 512; i = i+1) begin if (DBITS > 64) WR_DATA <= (xorshift64_state << (DBITS-64)) ^ xorshift64_state; else WR_DATA <= xorshift64_state; xorshift64_next; - WR_ADDR <= getaddr(i[7:4]); + WR_ADDR <= getaddr(i < 256 ? i[7:4] : xorshift64_state[63:60]); xorshift64_next; - RD_ADDR <= getaddr(i[3:0]); - WR_EN <= ^i; + RD_ADDR <= getaddr(i < 256 ? i[3:0] : xorshift64_state[59:56]); + WR_EN <= xorshift64_state[55]; xorshift64_next; #1; clk <= 1; From d1e38693d59b09f374f6228735932a347c3018b3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 7 Jan 2015 01:59:36 +0100 Subject: [PATCH 281/492] More Xilinx bram cleanups --- techlibs/xilinx/brams.v | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/techlibs/xilinx/brams.v b/techlibs/xilinx/brams.v index 83f2aede4..d9d5391b3 100644 --- a/techlibs/xilinx/brams.v +++ b/techlibs/xilinx/brams.v @@ -50,8 +50,8 @@ module \$__XILINX_RAMB36_SDP72 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .RAM_MODE("SDP"), .READ_WIDTH_A(72), .WRITE_WIDTH_B(72), - .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"), - .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST") ) _TECHMAP_REPLACE_ ( .DOBDO(DO[63:32]), .DOADO(DO[31:0]), @@ -127,8 +127,8 @@ module \$__XILINX_RAMB18_SDP36 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .RAM_MODE("SDP"), .READ_WIDTH_A(36), .WRITE_WIDTH_B(36), - .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"), - .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST") ) _TECHMAP_REPLACE_ ( .DOBDO(DO[31:16]), .DOADO(DO[15:0]), @@ -204,8 +204,8 @@ module \$__XILINX_RAMB18_TDP18 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .READ_WIDTH_B(18), .WRITE_WIDTH_A(18), .WRITE_WIDTH_B(18), - .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"), - .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST") ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), @@ -277,8 +277,8 @@ module \$__XILINX_RAMB18_TDP9 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .READ_WIDTH_B(9), .WRITE_WIDTH_A(9), .WRITE_WIDTH_B(9), - .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"), - .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST") ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), @@ -350,8 +350,8 @@ module \$__XILINX_RAMB18_TDP4 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .READ_WIDTH_B(4), .WRITE_WIDTH_A(4), .WRITE_WIDTH_B(4), - .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"), - .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST") ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), @@ -423,8 +423,8 @@ module \$__XILINX_RAMB18_TDP2 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .READ_WIDTH_B(2), .WRITE_WIDTH_A(2), .WRITE_WIDTH_B(2), - .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"), - .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST") ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), @@ -496,8 +496,8 @@ module \$__XILINX_RAMB18_TDP1 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .READ_WIDTH_B(1), .WRITE_WIDTH_A(1), .WRITE_WIDTH_B(1), - .WRITE_MODE_A(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"), - .WRITE_MODE_B(TRANSP2 ? "WRITE_FIRST" : "READ_FIRST") + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST") ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), From fd787609aad5fcd7a817c4a7da0f6d89894c551a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 7 Jan 2015 23:25:51 +0100 Subject: [PATCH 282/492] disabled problematic mux -> and/or transform --- passes/opt/opt_const.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc index 2eaba15ce..5d557b985 100644 --- a/passes/opt/opt_const.cc +++ b/passes/opt/opt_const.cc @@ -681,13 +681,17 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons goto next_cell; } + #if 0 + // disabled because replacing muxes with and/or gates sometimes causes probems with + // simulating undefs (e.g. lm32 from yosys-bigsim vs. icarus verilog init problems) + if (consume_x && mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\A") == RTLIL::SigSpec(0, 1)) { cover_list("opt.opt_const.mux_and", "$mux", "$_MUX_", cell->type.str()); log("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); cell->setPort("\\A", cell->getPort("\\S")); cell->unsetPort("\\S"); if (cell->type == "$mux") { - auto width = cell->parameters["\\WIDTH"]; + Const width = cell->parameters["\\WIDTH"]; cell->parameters["\\A_WIDTH"] = width; cell->parameters["\\B_WIDTH"] = width; cell->parameters["\\Y_WIDTH"] = width; @@ -707,7 +711,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cell->setPort("\\B", cell->getPort("\\S")); cell->unsetPort("\\S"); if (cell->type == "$mux") { - auto width = cell->parameters["\\WIDTH"]; + Const width = cell->parameters["\\WIDTH"]; cell->parameters["\\A_WIDTH"] = width; cell->parameters["\\B_WIDTH"] = width; cell->parameters["\\Y_WIDTH"] = width; @@ -720,6 +724,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons did_something = true; goto next_cell; } + #endif if (mux_undef && (cell->type == "$mux" || cell->type == "$pmux")) { RTLIL::SigSpec new_a, new_b, new_s; From 38dfc5c580c8ba418783ec8cbee1a78c7cd5f788 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 8 Jan 2015 00:05:11 +0100 Subject: [PATCH 283/492] added minimalistic xilinx sim models --- techlibs/xilinx/cells_sim.v | 150 ++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 techlibs/xilinx/cells_sim.v diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v new file mode 100644 index 000000000..849ea5640 --- /dev/null +++ b/techlibs/xilinx/cells_sim.v @@ -0,0 +1,150 @@ + +module IBUF(O, I); +output O; +input I; +assign O = I; +endmodule + +module OBUF(O, I); +output O; +input I; +assign O = I; +endmodule + +module BUFGP(O, I); +output O; +input I; +assign O = I; +endmodule + +module OBUFT(O, I, T); +output O; +input I, T; +assign O = T ? 1'bz : I; +endmodule + +module GND(G); +output G; +assign G = 0; +endmodule + +module INV(O, I); +input I; +output O; +assign O = !I; +endmodule + +module LUT1(O, I0); +parameter [1:0] INIT = 0; +input I0; +output O; +assign O = I0 ? INIT[1] : INIT[0]; +endmodule + +module LUT2(O, I0, I1); +parameter [3:0] INIT = 0; +input I0, I1; +output O; +wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0]; +assign O = I0 ? s1[1] : s1[0]; +endmodule + +module LUT3(O, I0, I1, I2); +parameter [7:0] INIT = 0; +input I0, I1, I2; +output O; +wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0]; +wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; +assign O = I0 ? s1[1] : s1[0]; +endmodule + +module LUT4(O, I0, I1, I2, I3); +parameter [15:0] INIT = 0; +input I0, I1, I2, I3; +output O; +wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0]; +wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; +wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; +assign O = I0 ? s1[1] : s1[0]; +endmodule + +module LUT5(O, I0, I1, I2, I3, I4); +parameter [31:0] INIT = 0; +input I0, I1, I2, I3, I4; +output O; +wire [15: 0] s4 = I4 ? INIT[31:16] : INIT[15: 0]; +wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0]; +wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; +wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; +assign O = I0 ? s1[1] : s1[0]; +endmodule + +module LUT6(O, I0, I1, I2, I3, I4, I5); +parameter [63:0] INIT = 0; +input I0, I1, I2, I3, I4, I5; +output O; +wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0]; +wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0]; +wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0]; +wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; +wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; +assign O = I0 ? s1[1] : s1[0]; +endmodule + +module MUXCY(O, CI, DI, S); +input CI, DI, S; +output O; +assign O = S ? CI : DI; +endmodule + +module MUXF7(O, I0, I1, S); +input I0, I1, S; +output O; +assign O = S ? I1 : I0; +endmodule + +module MUXF8(O, I0, I1, S); +input I0, I1, S; +output O; +assign O = S ? I1 : I0; +endmodule + +module VCC(P); +output P; +assign P = 1; +endmodule + +module XORCY(O, CI, LI); +input CI, LI; +output O; +assign O = CI ^ LI; +endmodule + +module CARRY4(CO, O, CI, CYINIT, DI, S); +output [3:0] CO, O; +input CI, CYINIT; +input [3:0] DI, S; +wire ci_or_cyinit; +assign O = S ^ {CO[2:0], ci_or_cyinit}; +assign CO[0] = S[0] ? ci_or_cyinit : DI[0]; +assign CO[1] = S[1] ? CO[0] : DI[1]; +assign CO[2] = S[2] ? CO[1] : DI[2]; +assign CO[3] = S[3] ? CO[2] : DI[3]; +assign ci_or_cyinit = CI | CYINIT; +endmodule + +/* +module FDRE (Q, C, CR, D, R); +parameter [0:0] INIT = 1'b0, +parameter [0:0] IS_C_INVERTED = 1'b0, +parameter [0:0] IS_D_INVERTED = 1'b0, +parameter [0:0] IS_R_INVERTED = 1'b0 +output Q; +input C; +input CE; +input D; +input R; +// -- FIXME -- +endmodule +*/ + From 1d96277f5d4c615ca4018d9a6e867c980db3b73a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 8 Jan 2015 00:23:18 +0100 Subject: [PATCH 284/492] Added add_share_file Makefile macro --- Makefile | 7 +++++++ techlibs/common/Makefile.inc | 31 ++++++------------------------- techlibs/xilinx/Makefile.inc | 17 ++++------------- 3 files changed, 17 insertions(+), 38 deletions(-) diff --git a/Makefile b/Makefile index 38e892131..8d2e7679d 100644 --- a/Makefile +++ b/Makefile @@ -143,6 +143,13 @@ ifeq ($(ENABLE_COVER),1) CXXFLAGS += -DYOSYS_ENABLE_COVER endif +define add_share_file +EXTRA_TARGETS += $(1)/$(notdir $(2)) +$(1)/$(notdir $(2)): $(2) + $$(P) mkdir -p $(1) + $$(Q) cp $(2) $(1)/$(notdir $(2)) +endef + ifeq ($(PRETTY), 1) P_STATUS = 0 P_OFFSET = 0 diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index 0607ca1a1..dc1e0ef66 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -9,29 +9,10 @@ techlibs/common/blackbox.v: techlibs/common/blackbox.sed techlibs/common/simlib. $(P) cat techlibs/common/simlib.v techlibs/common/simcells.v | $(SED) -rf techlibs/common/blackbox.sed > techlibs/common/blackbox.v.new $(Q) mv techlibs/common/blackbox.v.new techlibs/common/blackbox.v -EXTRA_TARGETS += share/simlib.v share/simcells.v share/techmap.v share/blackbox.v share/pmux2mux.v share/adff2dff.v - -share/simlib.v: techlibs/common/simlib.v - $(P) mkdir -p share - $(Q) cp techlibs/common/simlib.v share/simlib.v - -share/simcells.v: techlibs/common/simcells.v - $(P) mkdir -p share - $(Q) cp techlibs/common/simcells.v share/simcells.v - -share/techmap.v: techlibs/common/techmap.v - $(P) mkdir -p share - $(Q) cp techlibs/common/techmap.v share/techmap.v - -share/blackbox.v: techlibs/common/blackbox.v - $(P) mkdir -p share - $(Q) cp techlibs/common/blackbox.v share/blackbox.v - -share/pmux2mux.v: techlibs/common/pmux2mux.v - $(P) mkdir -p share - $(Q) cp techlibs/common/pmux2mux.v share/pmux2mux.v - -share/adff2dff.v: techlibs/common/adff2dff.v - $(P) mkdir -p share - $(Q) cp techlibs/common/adff2dff.v share/adff2dff.v +$(eval $(call add_share_file,share,techlibs/common/simlib.v)) +$(eval $(call add_share_file,share,techlibs/common/simcells.v)) +$(eval $(call add_share_file,share,techlibs/common/techmap.v)) +$(eval $(call add_share_file,share,techlibs/common/blackbox.v)) +$(eval $(call add_share_file,share,techlibs/common/pmux2mux.v)) +$(eval $(call add_share_file,share,techlibs/common/adff2dff.v)) diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 64ee9597c..b653660fa 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -1,17 +1,8 @@ OBJS += techlibs/xilinx/synth_xilinx.o -EXTRA_TARGETS += share/xilinx/cells.v share/xilinx/brams.txt share/xilinx/brams.v - -share/xilinx/cells.v: techlibs/xilinx/cells.v - $(P) mkdir -p share/xilinx - $(Q) cp techlibs/xilinx/cells.v share/xilinx/cells.v - -share/xilinx/brams.txt: techlibs/xilinx/brams.txt - $(P) mkdir -p share/xilinx - $(Q) cp techlibs/xilinx/brams.txt share/xilinx/brams.txt - -share/xilinx/brams.v: techlibs/xilinx/brams.v - $(P) mkdir -p share/xilinx - $(Q) cp techlibs/xilinx/brams.v share/xilinx/brams.v +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_sim.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams.txt)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams.v)) From 0ca889a4331b4439444a64b4b1fde9a31472fd1a Mon Sep 17 00:00:00 2001 From: Fabio Utzig Date: Thu, 8 Jan 2015 09:52:30 -0200 Subject: [PATCH 285/492] Add homebrew's readline paths --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 8d2e7679d..546f5722c 100644 --- a/Makefile +++ b/Makefile @@ -37,9 +37,9 @@ LDLIBS = -lstdc++ -lm SED = sed ifeq (Darwin,$(findstring Darwin,$(shell uname))) - # add macports include and library path to search directories, don't use '-rdynamic' and '-lrt': - CXXFLAGS += -I/opt/local/include - LDFLAGS += -L/opt/local/lib + # add macports/homebrew include and library path to search directories, don't use '-rdynamic' and '-lrt': + CXXFLAGS += -I/opt/local/include -I/usr/local/opt/readline/include + LDFLAGS += -L/opt/local/lib -L/usr/local/opt/readline/lib SED = gsed else LDFLAGS += -rdynamic From b16ed78b4317448828ce4b3163ab8a5f94ef1891 Mon Sep 17 00:00:00 2001 From: Fabio Utzig Date: Thu, 8 Jan 2015 09:54:28 -0200 Subject: [PATCH 286/492] Add homebrew's libffi paths --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 546f5722c..970c11b8e 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,9 @@ ifeq (Darwin,$(findstring Darwin,$(shell uname))) # add macports/homebrew include and library path to search directories, don't use '-rdynamic' and '-lrt': CXXFLAGS += -I/opt/local/include -I/usr/local/opt/readline/include LDFLAGS += -L/opt/local/lib -L/usr/local/opt/readline/lib + # add homebrew's libffi include and library path + CXXFLAGS += $(shell PKG_CONFIG_PATH=$$(brew list libffi | grep pkgconfig | xargs dirname) pkg-config --silence-errors --cflags libffi) + LDFLAGS += $(shell PKG_CONFIG_PATH=$$(brew list libffi | grep pkgconfig | xargs dirname) pkg-config --silence-errors --libs libffi) SED = gsed else LDFLAGS += -rdynamic From fff6f00b3c8704473bbb8149c82a2805fb1c32d2 Mon Sep 17 00:00:00 2001 From: Fabio Utzig Date: Thu, 8 Jan 2015 09:56:20 -0200 Subject: [PATCH 287/492] Enable bison to be customized --- Makefile | 1 + frontends/ilang/Makefile.inc | 2 +- frontends/verilog/Makefile.inc | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 970c11b8e..0ac0b7efd 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,7 @@ CXXFLAGS = -Wall -Wextra -ggdb -I"$(shell pwd)" -MD -DYOSYS_SRC='"$(shell pwd)"' LDFLAGS = -L${DESTDIR}/lib LDLIBS = -lstdc++ -lm SED = sed +BISON = bison ifeq (Darwin,$(findstring Darwin,$(shell uname))) # add macports/homebrew include and library path to search directories, don't use '-rdynamic' and '-lrt': diff --git a/frontends/ilang/Makefile.inc b/frontends/ilang/Makefile.inc index 984d436c6..c15e2cc47 100644 --- a/frontends/ilang/Makefile.inc +++ b/frontends/ilang/Makefile.inc @@ -5,7 +5,7 @@ GENFILES += frontends/ilang/ilang_parser.output GENFILES += frontends/ilang/ilang_lexer.cc frontends/ilang/ilang_parser.tab.cc: frontends/ilang/ilang_parser.y - $(P) bison -d -r all -b frontends/ilang/ilang_parser frontends/ilang/ilang_parser.y + $(P) $(BISON) -d -r all -b frontends/ilang/ilang_parser frontends/ilang/ilang_parser.y $(Q) mv frontends/ilang/ilang_parser.tab.c frontends/ilang/ilang_parser.tab.cc frontends/ilang/ilang_parser.tab.h: frontends/ilang/ilang_parser.tab.cc diff --git a/frontends/verilog/Makefile.inc b/frontends/verilog/Makefile.inc index 1b6854bb5..92cbd0b87 100644 --- a/frontends/verilog/Makefile.inc +++ b/frontends/verilog/Makefile.inc @@ -5,7 +5,7 @@ GENFILES += frontends/verilog/verilog_parser.output GENFILES += frontends/verilog/verilog_lexer.cc frontends/verilog/verilog_parser.tab.cc: frontends/verilog/verilog_parser.y - $(P) bison -d -r all -b frontends/verilog/verilog_parser frontends/verilog/verilog_parser.y + $(P) $(BISON) -d -r all -b frontends/verilog/verilog_parser frontends/verilog/verilog_parser.y $(Q) mv frontends/verilog/verilog_parser.tab.c frontends/verilog/verilog_parser.tab.cc frontends/verilog/verilog_parser.tab.h: frontends/verilog/verilog_parser.tab.cc From 0a231f96d79d3eae927bf33571846c98f78eedfd Mon Sep 17 00:00:00 2001 From: Fabio Utzig Date: Thu, 8 Jan 2015 09:58:24 -0200 Subject: [PATCH 288/492] Enable use of homebrew's provided bison if available --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 0ac0b7efd..a3aa2a397 100644 --- a/Makefile +++ b/Makefile @@ -44,6 +44,8 @@ ifeq (Darwin,$(findstring Darwin,$(shell uname))) # add homebrew's libffi include and library path CXXFLAGS += $(shell PKG_CONFIG_PATH=$$(brew list libffi | grep pkgconfig | xargs dirname) pkg-config --silence-errors --cflags libffi) LDFLAGS += $(shell PKG_CONFIG_PATH=$$(brew list libffi | grep pkgconfig | xargs dirname) pkg-config --silence-errors --libs libffi) + # use bison installed by homebrew if available + BISON = $(shell (brew list bison | grep -m1 "bin/bison") || echo bison) SED = gsed else LDFLAGS += -rdynamic From 95f1eb9b87064719c17d45f24775c3e97497b6df Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 9 Jan 2015 17:32:53 +0100 Subject: [PATCH 289/492] Only enable code coverage counters on linux --- kernel/driver.cc | 2 +- kernel/log.cc | 2 +- kernel/log.h | 4 ++-- passes/cmds/cover.cc | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index 1698e216c..c7f233c54 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -406,7 +406,7 @@ int main(int argc, char **argv) } } -#ifdef YOSYS_ENABLE_COVER +#if defined(YOSYS_ENABLE_COVER) && defined(__linux__) if (getenv("YOSYS_COVER_DIR") || getenv("YOSYS_COVER_FILE")) { string filename; diff --git a/kernel/log.cc b/kernel/log.cc index 70bff8f5b..401dbeeb0 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -402,7 +402,7 @@ void log_cell(RTLIL::Cell *cell, std::string indent) // --------------------------------------------------- // This is the magic behind the code coverage counters // --------------------------------------------------- -#ifdef YOSYS_ENABLE_COVER +#if defined(YOSYS_ENABLE_COVER) && defined(__linux__) dict> extra_coverage_data; diff --git a/kernel/log.h b/kernel/log.h index fa02d2396..e61d19b62 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -92,10 +92,10 @@ static inline void log_assert_worker(bool cond, const char *expr, const char *fi // This is the magic behind the code coverage counters // --------------------------------------------------- -#ifdef YOSYS_ENABLE_COVER +#if defined(YOSYS_ENABLE_COVER) && defined(__linux__) #define cover(_id) do { \ - static CoverData __d YS_ATTRIBUTE(section("yosys_cover_list"), aligned(1), used) = { __FILE__, __FUNCTION__, _id, __LINE__, 0 }; \ + static CoverData __d __attribute__((section("yosys_cover_list"), aligned(1), used)) = { __FILE__, __FUNCTION__, _id, __LINE__, 0 }; \ __d.counter++; \ } while (0) diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc index 6a70d1de9..5644066af 100644 --- a/passes/cmds/cover.cc +++ b/passes/cmds/cover.cc @@ -80,7 +80,7 @@ struct CoverPass : public Pass { log(" printf \"%%-60s %%10d %%s\\n\", p[i], c[i], i; }' {files} | sort -k3\n"); log("\n"); log("\n"); - log("Coverage counters are only available in debug builds of Yosys for Linux.\n"); + log("Coverage counters are only available in Yosys for Linux.\n"); log("\n"); } virtual void execute(std::vector args, RTLIL::Design *design) @@ -128,7 +128,7 @@ struct CoverPass : public Pass { log("\n"); } -#ifdef YOSYS_ENABLE_COVER +#if defined(YOSYS_ENABLE_COVER) && defined(__linux__) for (auto &it : get_coverage_data()) { if (!patterns.empty()) { for (auto &p : patterns) From dd699e03c111d11c7780863773993df34fee1726 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 13 Jan 2015 12:21:27 +0100 Subject: [PATCH 290/492] Small Makefile typo fix --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index a3aa2a397..a1e2cb76b 100644 --- a/Makefile +++ b/Makefile @@ -31,8 +31,8 @@ SMALL = 0 all: top-all -CXXFLAGS = -Wall -Wextra -ggdb -I"$(shell pwd)" -MD -DYOSYS_SRC='"$(shell pwd)"' -D_YOSYS_ -fPIC -I${DESTDIR}/include -LDFLAGS = -L${DESTDIR}/lib +CXXFLAGS = -Wall -Wextra -ggdb -I"$(shell pwd)" -MD -DYOSYS_SRC='"$(shell pwd)"' -D_YOSYS_ -fPIC -I$(DESTDIR)/include +LDFLAGS = -L$(DESTDIR)/lib LDLIBS = -lstdc++ -lm SED = sed BISON = bison From dfa42e272cd13a08314299817423052488eb58ab Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 13 Jan 2015 12:59:29 +0100 Subject: [PATCH 291/492] Tiny fix in vcdcd.pl --- tests/tools/vcdcd.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/tools/vcdcd.pl b/tests/tools/vcdcd.pl index 2abfb7a21..6f497e99c 100755 --- a/tests/tools/vcdcd.pl +++ b/tests/tools/vcdcd.pl @@ -80,8 +80,8 @@ for my $net (sort keys %gold_signals_hash) { for my $fullname (keys $gate_signals_hash{$net}) { $orig_net_names{$fullname} = 1; } - for my $_ (sort keys %orig_net_names) { - push @signals, $_; + for my $net (sort keys %orig_net_names) { + push @signals, $net; print " $1" if /(\[([0-9]+|[0-9]+:[0-9]+)\])$/; } print "\n"; From 8426884b4052deeebf25b80d105adf1c2a5a5698 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 13 Jan 2015 13:20:09 +0100 Subject: [PATCH 292/492] Re-enabled mux->and/or transform (and fixed lm32 in yosys-bigsim) --- passes/opt/opt_const.cc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc index 5d557b985..6a830dd0d 100644 --- a/passes/opt/opt_const.cc +++ b/passes/opt/opt_const.cc @@ -681,10 +681,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons goto next_cell; } - #if 0 - // disabled because replacing muxes with and/or gates sometimes causes probems with - // simulating undefs (e.g. lm32 from yosys-bigsim vs. icarus verilog init problems) - if (consume_x && mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\A") == RTLIL::SigSpec(0, 1)) { cover_list("opt.opt_const.mux_and", "$mux", "$_MUX_", cell->type.str()); log("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); @@ -724,7 +720,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons did_something = true; goto next_cell; } - #endif if (mux_undef && (cell->type == "$mux" || cell->type == "$pmux")) { RTLIL::SigSpec new_a, new_b, new_s; From 153d3dd4e0b6e8725e2afbc973cbc1e836cb0703 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 13 Jan 2015 13:20:32 +0100 Subject: [PATCH 293/492] Various cleanups in synth_xilinx command --- techlibs/xilinx/synth_xilinx.cc | 62 +++++---------------------------- 1 file changed, 8 insertions(+), 54 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index a0783740b..e7308461a 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -43,16 +43,12 @@ struct SynthXilinxPass : public Pass { log(" synth_xilinx [options]\n"); log("\n"); log("This command runs synthesis for Xilinx FPGAs. This command does not operate on\n"); - log("partly selected designs.\n"); + log("partly selected designs. At the moment this command creates netlists that are\n"); + log("compatible with 7-series and 6-series Xilinx devices.\n"); log("\n"); log(" -top \n"); log(" use the specified module as top module (default='top')\n"); log("\n"); - log(" -arch \n"); - log(" select architecture. the following architectures are supported:\n"); - log(" spartan6 (default), artix7, kintex7, virtex7, zynq7000\n"); - log(" (this parameter is not used by the command at the moment)\n"); - log("\n"); log(" -edif \n"); log(" write the design to the specified edif file. writing of an output file\n"); log(" is omitted if this parameter is not specified.\n"); @@ -70,6 +66,8 @@ struct SynthXilinxPass : public Pass { log("\n"); log(" coarse:\n"); log(" synth -run coarse\n"); + log("\n"); + log(" bram:\n"); log(" memory_bram -rules +/xilinx/brams.txt\n"); log(" techmap -map +/xilinx/brams.v\n"); log("\n"); @@ -84,18 +82,6 @@ struct SynthXilinxPass : public Pass { log(" techmap -map +/xilinx/cells.v\n"); log(" clean\n"); log("\n"); - log(" flatten:\n"); - log(" flatten\n"); - log(" opt -fast -full\n"); - log("\n"); - log(" clkbuf:\n"); - log(" select -set xilinx_clocks /t:FDRE %%x:+FDRE[C] /t:FDRE %%d\n"); - log(" iopadmap -bits -inpad BUFGP O:I @xilinx_clocks\n"); - log("\n"); - log(" iobuf:\n"); - log(" select -set xilinx_nonclocks /w:* /t:BUFGP %%x:+BUFGP[I] %%d\n"); - log(" iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I @xilinx_nonclocks\n"); - log("\n"); log(" edif:\n"); log(" write_edif synth.edif\n"); log("\n"); @@ -114,10 +100,6 @@ struct SynthXilinxPass : public Pass { top_module = args[++argidx]; continue; } - if (args[argidx] == "-arch" && argidx+1 < args.size()) { - arch_name = args[++argidx]; - continue; - } if (args[argidx] == "-edif" && argidx+1 < args.size()) { edif_file = args[++argidx]; continue; @@ -137,20 +119,6 @@ struct SynthXilinxPass : public Pass { if (!design->full_selection()) log_cmd_error("This comannd only operates on fully selected designs!\n"); - if (arch_name == "spartan6") { - /* set flags */ - } else - if (arch_name == "artix7") { - /* set flags */ - } else - if (arch_name == "kintex7") { - /* set flags */ - } else - if (arch_name == "zynq7000") { - /* set flags */ - } else - log_cmd_error("Architecture '%s' is not supported!\n", arch_name.c_str()); - bool active = run_from.empty(); log_header("Executing SYNTH_XILINX pass.\n"); @@ -164,6 +132,10 @@ struct SynthXilinxPass : public Pass { if (check_label(active, run_from, run_to, "coarse")) { Pass::call(design, "synth -run coarse"); + } + + if (check_label(active, run_from, run_to, "bram")) + { Pass::call(design, "memory_bram -rules +/xilinx/brams.txt"); Pass::call(design, "techmap -map +/xilinx/brams.v"); } @@ -185,24 +157,6 @@ struct SynthXilinxPass : public Pass { Pass::call(design, "clean"); } - if (check_label(active, run_from, run_to, "flatten")) - { - Pass::call(design, "flatten"); - Pass::call(design, "opt -fast -full"); - } - - if (check_label(active, run_from, run_to, "clkbuf")) - { - Pass::call(design, stringf("select -set xilinx_clocks %s/t:FDRE %%x:+FDRE[C] %s/t:FDRE %%d", top_module.c_str(), top_module.c_str())); - Pass::call(design, "iopadmap -bits -inpad BUFGP O:I @xilinx_clocks"); - } - - if (check_label(active, run_from, run_to, "iobuf")) - { - Pass::call(design, stringf("select -set xilinx_nonclocks %s/w:* %s/t:BUFGP %%x:+BUFGP[I] %%d", top_module.c_str(), top_module.c_str())); - Pass::call(design, "iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I @xilinx_nonclocks"); - } - if (check_label(active, run_from, run_to, "edif")) { if (!edif_file.empty()) From 8e8e791fb5dba3eb0a236cbed8c13bd5ac5ce96c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 15 Jan 2015 12:41:52 +0100 Subject: [PATCH 294/492] Consolidate "Blocking assignment to memory.." msgs for the same line --- frontends/ast/simplify.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 2ce2d57dc..5ab778e66 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -51,6 +51,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, { AstNode *newNode = NULL; bool did_something = false; + static pair last_blocking_assignment_warn; #if 0 log("-------------\n"); @@ -62,6 +63,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (stage == 0) { log_assert(type == AST_MODULE); + last_blocking_assignment_warn = pair(); while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { } @@ -1259,9 +1261,13 @@ skip_dynamic_range_lvalue_expansion:; sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++); std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN"; - if (type == AST_ASSIGN_EQ) - log_warning("Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n", - filename.c_str(), linenum); + if (type == AST_ASSIGN_EQ) { + pair this_blocking_assignment_warn(filename, linenum); + if (this_blocking_assignment_warn != last_blocking_assignment_warn) + log_warning("Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n", + filename.c_str(), linenum); + last_blocking_assignment_warn = this_blocking_assignment_warn; + } int mem_width, mem_size, addr_bits; children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits); From a588a4a5c95d14e62678c98b14af139903980be3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 15 Jan 2015 12:53:12 +0100 Subject: [PATCH 295/492] Fixed handling of "input foo; reg [0:0] foo;" --- frontends/ast/simplify.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 5ab778e66..552fc04bc 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -186,6 +186,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, AstNode *first_node = this_wire_scope[node->str]; if (!node->is_input && !node->is_output && node->is_reg && node->children.size() == 0) goto wires_are_compatible; + if (first_node->children.size() == 0 && node->children.size() == 1 && node->children[0]->type == AST_RANGE) { + AstNode *r = node->children[0]; + if (r->range_valid && r->range_left == 0 && r->range_right == 0) { + delete r; + node->children.pop_back(); + } + } if (first_node->children.size() != node->children.size()) goto wires_are_incompatible; for (size_t j = 0; j < node->children.size(); j++) { From df9d096a7d88955dcf44d9e30a9ba49238b478db Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 15 Jan 2015 13:08:19 +0100 Subject: [PATCH 296/492] Ignoring more system task and functions --- frontends/ast/simplify.cc | 4 +++- frontends/verilog/verilog_lexer.l | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 552fc04bc..6128ac684 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -157,7 +157,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, return false; // deactivate all calls to non-synthesis system taks - if ((type == AST_FCALL || type == AST_TCALL) && (str == "$display" || str == "$stop" || str == "$finish")) { + if ((type == AST_FCALL || type == AST_TCALL) && (str == "$display" || str == "$strobe" || str == "$monitor" || str == "$time" || str == "$stop" || str == "$finish" || + str == "$dumpfile" || str == "$dumpvars" || str == "$dumpon" || str == "$dumpoff" || str == "$dumpall")) { + log_warning("Ignoring call to system %s %s at %s:%d.\n", type == AST_FCALL ? "function" : "task", str.c_str(), filename.c_str(), linenum); delete_children(); str = std::string(); } diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 42b5bf7ea..cb8fafcb2 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -240,7 +240,7 @@ and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 { supply0 { return TOK_SUPPLY0; } supply1 { return TOK_SUPPLY1; } -"$"(display|time|stop|finish) { +"$"(display|strobe|monitor|time|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) { frontend_verilog_yylval.string = new std::string(yytext); return TOK_ID; } From 9065fb25cc3fd21cf77b041cbec1d8a12b33728d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 15 Jan 2015 13:36:57 +0100 Subject: [PATCH 297/492] Fixed handling of foo.__TECHMAP_... --- passes/techmap/techmap.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 94dd4d42c..b1a40b25e 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -129,7 +129,7 @@ struct TechmapWorker continue; const char *q = strrchr(p+1, '.'); - p = q ? q : p+1; + p = q ? q+1 : p+1; if (!strncmp(p, "_TECHMAP_", 9)) { TechmapWireData record; From 2e36faeced76fe0a4d19a1febddd070263955034 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 15 Jan 2015 13:37:48 +0100 Subject: [PATCH 298/492] Added "abc -lut w1:w2" --- passes/abc/abc.cc | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 78d8fc434..16b66d47d 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -587,7 +587,7 @@ struct abc_output_filter }; void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, - std::string liberty_file, std::string constr_file, bool cleanup, int lut_mode, bool dff_mode, std::string clk_str, + std::string liberty_file, std::string constr_file, bool cleanup, int lut_mode, int lut_mode2, bool dff_mode, std::string clk_str, bool keepff, std::string delay_target, bool fast_mode, const std::vector &cells, bool show_tempdir) { module = current_module; @@ -853,6 +853,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); for (int i = 0; i < lut_mode; i++) fprintf(f, "%d 1.00 1.00\n", i+1); + for (int i = lut_mode; i < lut_mode2; i++) + fprintf(f, "%d %d.00 1.00\n", i+1, 2 << (i - lut_mode)); fclose(f); } @@ -1142,6 +1144,12 @@ struct AbcPass : public Pass { log(" -lut \n"); log(" generate netlist using luts of (max) the specified width.\n"); log("\n"); + log(" -lut :\n"); + log(" generate netlist using luts of (max) the specified width . All\n"); + log(" luts with width <= have constant cost. for luts larger than \n"); + log(" the area cost doubles with each additional input bit. the delay cost\n"); + log(" is still constant for all lut widths.\n"); + log("\n"); log(" -dff\n"); log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n"); log(" clock domains are automatically partitioned in clock domains and each\n"); @@ -1186,7 +1194,7 @@ struct AbcPass : public Pass { std::string script_file, liberty_file, constr_file, clk_str, delay_target; bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; bool show_tempdir = false; - int lut_mode = 0; + int lut_mode = 0, lut_mode2 = 0; markgroups = false; #ifdef _WIN32 @@ -1229,7 +1237,15 @@ struct AbcPass : public Pass { continue; } if (arg == "-lut" && argidx+1 < args.size()) { - lut_mode = atoi(args[++argidx].c_str()); + string arg = args[++argidx]; + size_t pos = arg.find_first_of(':'); + if (pos != string::npos) { + lut_mode = atoi(arg.substr(0, pos).c_str()); + lut_mode2 = atoi(arg.substr(pos+1).c_str()); + } else { + lut_mode = atoi(arg.c_str()); + lut_mode2 = lut_mode; + } continue; } if (arg == "-fast") { @@ -1274,7 +1290,7 @@ struct AbcPass : public Pass { if (mod->processes.size() > 0) log("Skipping module %s as it contains processes.\n", log_id(mod)); else if (!dff_mode || !clk_str.empty()) - abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, dff_mode, clk_str, keepff, delay_target, fast_mode, mod->selected_cells(), show_tempdir); + abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, lut_mode2, dff_mode, clk_str, keepff, delay_target, fast_mode, mod->selected_cells(), show_tempdir); else { assign_map.set(mod); @@ -1418,7 +1434,7 @@ struct AbcPass : public Pass { clk_sig = assign_map(std::get<1>(it.first)); en_polarity = std::get<2>(it.first); en_sig = assign_map(std::get<3>(it.first)); - abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, + abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, lut_mode2, !clk_sig.empty(), "$", keepff, delay_target, fast_mode, it.second, show_tempdir); assign_map.set(mod); } From b197279f3c2d7b487d69cafca8dfc5edb4b2eaa8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 15 Jan 2015 13:50:04 +0100 Subject: [PATCH 299/492] Added Xilinx MUXF7 and MUXF8 support --- techlibs/xilinx/cells.v | 28 ++++++++++++++++++++++++++++ techlibs/xilinx/synth_xilinx.cc | 4 ++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/cells.v b/techlibs/xilinx/cells.v index d19be0db7..75253f57b 100644 --- a/techlibs/xilinx/cells.v +++ b/techlibs/xilinx/cells.v @@ -45,6 +45,34 @@ module \$lut (A, Y); LUT6 #(.INIT(LUT)) fpga_lut (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]), .I4(A[4]), .I5(A[5])); + end else + if (WIDTH == 7) begin:lut7 + wire T0, T1; + LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); + LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); + MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6])); + end else + if (WIDTH == 8) begin:lut8 + wire T0, T1, T2, T3, T4, T5; + LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); + LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); + LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); + LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); + MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6])); + MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6])); + MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7])); end else begin:error wire _TECHMAP_FAIL_ = 1; end diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index e7308461a..380fdae73 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -75,7 +75,7 @@ struct SynthXilinxPass : public Pass { log(" synth -run fine\n"); log("\n"); log(" map_luts:\n"); - log(" abc -lut 6\n"); + log(" abc -lut 6:8\n"); log(" clean\n"); log("\n"); log(" map_cells:\n"); @@ -147,7 +147,7 @@ struct SynthXilinxPass : public Pass { if (check_label(active, run_from, run_to, "map_luts")) { - Pass::call(design, "abc -lut 6"); + Pass::call(design, "abc -lut 6:8"); Pass::call(design, "clean"); } From fd8c8d4fd386c225b13ec02f47ce32905b9eb7d2 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 16 Jan 2015 14:59:40 +0100 Subject: [PATCH 300/492] Added FF cells to xilinx/cells_sim.v --- techlibs/xilinx/cells_sim.v | 222 ++++++++++++++++++------------------ 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 849ea5640..cb290db80 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -1,150 +1,150 @@ -module IBUF(O, I); -output O; -input I; -assign O = I; +module VCC(output P); + assign P = 1; endmodule -module OBUF(O, I); -output O; -input I; -assign O = I; +module GND(output G); + assign G = 0; endmodule -module BUFGP(O, I); -output O; -input I; -assign O = I; +module IBUF(output O, input I); + assign O = I; endmodule -module OBUFT(O, I, T); -output O; -input I, T; -assign O = T ? 1'bz : I; +module OBUF(output O, input I); + assign O = I; endmodule -module GND(G); -output G; -assign G = 0; +module BUFGP(output O, input I); + assign O = I; endmodule -module INV(O, I); -input I; -output O; -assign O = !I; +module OBUFT(output O, input I, T); + assign O = T ? 1'bz : I; endmodule -module LUT1(O, I0); -parameter [1:0] INIT = 0; -input I0; -output O; -assign O = I0 ? INIT[1] : INIT[0]; +module INV(output O, input I); + assign O = !I; endmodule -module LUT2(O, I0, I1); -parameter [3:0] INIT = 0; -input I0, I1; -output O; -wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0]; -assign O = I0 ? s1[1] : s1[0]; +module LUT1(output O, input I0); + parameter [1:0] INIT = 0; + assign O = I0 ? INIT[1] : INIT[0]; endmodule -module LUT3(O, I0, I1, I2); -parameter [7:0] INIT = 0; -input I0, I1, I2; -output O; -wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0]; -wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; -assign O = I0 ? s1[1] : s1[0]; +module LUT2(output O, input I0, I1); + parameter [3:0] INIT = 0; + wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0]; + assign O = I0 ? s1[1] : s1[0]; endmodule -module LUT4(O, I0, I1, I2, I3); -parameter [15:0] INIT = 0; -input I0, I1, I2, I3; -output O; -wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0]; -wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; -wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; -assign O = I0 ? s1[1] : s1[0]; +module LUT3(output O, input I0, I1, I2); + parameter [7:0] INIT = 0; + wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0]; + wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; + assign O = I0 ? s1[1] : s1[0]; endmodule -module LUT5(O, I0, I1, I2, I3, I4); -parameter [31:0] INIT = 0; -input I0, I1, I2, I3, I4; -output O; -wire [15: 0] s4 = I4 ? INIT[31:16] : INIT[15: 0]; -wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0]; -wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; -wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; -assign O = I0 ? s1[1] : s1[0]; +module LUT4(output O, input I0, I1, I2, I3); + parameter [15:0] INIT = 0; + wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0]; + wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; + wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; + assign O = I0 ? s1[1] : s1[0]; endmodule -module LUT6(O, I0, I1, I2, I3, I4, I5); -parameter [63:0] INIT = 0; -input I0, I1, I2, I3, I4, I5; -output O; -wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0]; -wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0]; -wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0]; -wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; -wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; -assign O = I0 ? s1[1] : s1[0]; +module LUT5(output O, input I0, I1, I2, I3, I4); + parameter [31:0] INIT = 0; + wire [15: 0] s4 = I4 ? INIT[31:16] : INIT[15: 0]; + wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0]; + wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; + wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; + assign O = I0 ? s1[1] : s1[0]; endmodule -module MUXCY(O, CI, DI, S); -input CI, DI, S; -output O; -assign O = S ? CI : DI; +module LUT6(output O, input I0, I1, I2, I3, I4, I5); + parameter [63:0] INIT = 0; + wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0]; + wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0]; + wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0]; + wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; + wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; + assign O = I0 ? s1[1] : s1[0]; endmodule -module MUXF7(O, I0, I1, S); -input I0, I1, S; -output O; -assign O = S ? I1 : I0; +module MUXCY(output O, input CI, DI, S); + assign O = S ? CI : DI; endmodule -module MUXF8(O, I0, I1, S); -input I0, I1, S; -output O; -assign O = S ? I1 : I0; +module MUXF7(output O, input I0, I1, S); + assign O = S ? I1 : I0; endmodule -module VCC(P); -output P; -assign P = 1; +module MUXF8(output O, input I0, I1, S); + assign O = S ? I1 : I0; endmodule -module XORCY(O, CI, LI); -input CI, LI; -output O; -assign O = CI ^ LI; +module XORCY(output O, input CI, LI); + assign O = CI ^ LI; endmodule -module CARRY4(CO, O, CI, CYINIT, DI, S); -output [3:0] CO, O; -input CI, CYINIT; -input [3:0] DI, S; -wire ci_or_cyinit; -assign O = S ^ {CO[2:0], ci_or_cyinit}; -assign CO[0] = S[0] ? ci_or_cyinit : DI[0]; -assign CO[1] = S[1] ? CO[0] : DI[1]; -assign CO[2] = S[2] ? CO[1] : DI[2]; -assign CO[3] = S[3] ? CO[2] : DI[3]; -assign ci_or_cyinit = CI | CYINIT; +module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S); + assign O = S ^ {CO[2:0], CI | CYINIT}; + assign CO[0] = S[0] ? CI | CYINIT : DI[0]; + assign CO[1] = S[1] ? CO[0] : DI[1]; + assign CO[2] = S[2] ? CO[1] : DI[2]; + assign CO[3] = S[3] ? CO[2] : DI[3]; endmodule -/* -module FDRE (Q, C, CR, D, R); -parameter [0:0] INIT = 1'b0, -parameter [0:0] IS_C_INVERTED = 1'b0, -parameter [0:0] IS_D_INVERTED = 1'b0, -parameter [0:0] IS_R_INVERTED = 1'b0 -output Q; -input C; -input CE; -input D; -input R; -// -- FIXME -- +module FDRE (output reg Q, input C, CE, D, R); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_R_INVERTED = 1'b0; + initial Q <= INIT; + generate case (|IS_C_INVERTED) + 1'b0: always @(posedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 1'b1: always @(negedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + endcase endgenerate +endmodule + +module FDSE (output reg Q, input C, CE, D, S); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_S_INVERTED = 1'b0; + initial Q <= INIT; + generate case (|IS_C_INVERTED) + 1'b0: always @(posedge C) if (S == !IS_S_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 1'b1: always @(negedge C) if (S == !IS_S_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + endcase endgenerate +endmodule + +module FDCE (output reg Q, input C, CE, D, CLR); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_CLR_INVERTED = 1'b0; + initial Q <= INIT; + generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) + 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + endcase endgenerate +endmodule + +module FDPE (output reg Q, input C, CE, D, PRE); + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_PRE_INVERTED = 1'b0; + initial Q <= INIT; + generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED}) + 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + endcase endgenerate endmodule -*/ From 6b091533202791f754136577c7595edf756914dc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 16 Jan 2015 15:11:56 +0100 Subject: [PATCH 301/492] Fixed xilinx bram clock inverted config --- techlibs/xilinx/brams.v | 56 +++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/techlibs/xilinx/brams.v b/techlibs/xilinx/brams.v index d9d5391b3..89ae07eb6 100644 --- a/techlibs/xilinx/brams.v +++ b/techlibs/xilinx/brams.v @@ -51,7 +51,9 @@ module \$__XILINX_RAMB36_SDP72 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .READ_WIDTH_A(72), .WRITE_WIDTH_B(72), .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST") + .WRITE_MODE_B("READ_FIRST"), + .IS_CLKARDCLK_INVERTED(!CLKPOL2), + .IS_CLKBWRCLK_INVERTED(!CLKPOL3) ) _TECHMAP_REPLACE_ ( .DOBDO(DO[63:32]), .DOADO(DO[31:0]), @@ -63,7 +65,7 @@ module \$__XILINX_RAMB36_SDP72 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .DIPADIP(DIP[3:0]), .ADDRARDADDR(A1ADDR_16), - .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), + .CLKARDCLK(CLK2), .ENARDEN(|1), .REGCEAREGCE(|1), .RSTRAMARSTRAM(|0), @@ -71,7 +73,7 @@ module \$__XILINX_RAMB36_SDP72 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .WEA(4'b0), .ADDRBWRADDR(B1ADDR_16), - .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), + .CLKBWRCLK(CLK3), .ENBWREN(|1), .REGCEB(|0), .RSTRAMB(|0), @@ -128,7 +130,9 @@ module \$__XILINX_RAMB18_SDP36 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .READ_WIDTH_A(36), .WRITE_WIDTH_B(36), .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST") + .WRITE_MODE_B("READ_FIRST"), + .IS_CLKARDCLK_INVERTED(!CLKPOL2), + .IS_CLKBWRCLK_INVERTED(!CLKPOL3) ) _TECHMAP_REPLACE_ ( .DOBDO(DO[31:16]), .DOADO(DO[15:0]), @@ -140,7 +144,7 @@ module \$__XILINX_RAMB18_SDP36 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .DIPADIP(DIP[1:0]), .ADDRARDADDR(A1ADDR_14), - .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), + .CLKARDCLK(CLK2), .ENARDEN(|1), .REGCEAREGCE(|1), .RSTRAMARSTRAM(|0), @@ -148,7 +152,7 @@ module \$__XILINX_RAMB18_SDP36 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .WEA(2'b0), .ADDRBWRADDR(B1ADDR_14), - .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), + .CLKBWRCLK(CLK3), .ENBWREN(|1), .REGCEB(|0), .RSTRAMB(|0), @@ -205,14 +209,16 @@ module \$__XILINX_RAMB18_TDP18 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .WRITE_WIDTH_A(18), .WRITE_WIDTH_B(18), .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST") + .WRITE_MODE_B("READ_FIRST"), + .IS_CLKARDCLK_INVERTED(!CLKPOL2), + .IS_CLKBWRCLK_INVERTED(!CLKPOL3) ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), .DOADO(DO), .DOPADOP(DOP), .ADDRARDADDR(A1ADDR_14), - .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), + .CLKARDCLK(CLK2), .ENARDEN(|1), .REGCEAREGCE(|1), .RSTRAMARSTRAM(|0), @@ -222,7 +228,7 @@ module \$__XILINX_RAMB18_TDP18 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN .DIBDI(DI), .DIPBDIP(DIP), .ADDRBWRADDR(B1ADDR_14), - .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), + .CLKBWRCLK(CLK3), .ENBWREN(|1), .REGCEB(|0), .RSTRAMB(|0), @@ -278,14 +284,16 @@ module \$__XILINX_RAMB18_TDP9 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .WRITE_WIDTH_A(9), .WRITE_WIDTH_B(9), .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST") + .WRITE_MODE_B("READ_FIRST"), + .IS_CLKARDCLK_INVERTED(!CLKPOL2), + .IS_CLKBWRCLK_INVERTED(!CLKPOL3) ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), .DOADO(DO), .DOPADOP(DOP), .ADDRARDADDR(A1ADDR_14), - .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), + .CLKARDCLK(CLK2), .ENARDEN(|1), .REGCEAREGCE(|1), .RSTRAMARSTRAM(|0), @@ -295,7 +303,7 @@ module \$__XILINX_RAMB18_TDP9 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .DIBDI(DI), .DIPBDIP(DIP), .ADDRBWRADDR(B1ADDR_14), - .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), + .CLKBWRCLK(CLK3), .ENBWREN(|1), .REGCEB(|0), .RSTRAMB(|0), @@ -351,14 +359,16 @@ module \$__XILINX_RAMB18_TDP4 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .WRITE_WIDTH_A(4), .WRITE_WIDTH_B(4), .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST") + .WRITE_MODE_B("READ_FIRST"), + .IS_CLKARDCLK_INVERTED(!CLKPOL2), + .IS_CLKBWRCLK_INVERTED(!CLKPOL3) ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), .DOADO(DO), .DOPADOP(DOP), .ADDRARDADDR(A1ADDR_14), - .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), + .CLKARDCLK(CLK2), .ENARDEN(|1), .REGCEAREGCE(|1), .RSTRAMARSTRAM(|0), @@ -368,7 +378,7 @@ module \$__XILINX_RAMB18_TDP4 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .DIBDI(DI), .DIPBDIP(DIP), .ADDRBWRADDR(B1ADDR_14), - .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), + .CLKBWRCLK(CLK3), .ENBWREN(|1), .REGCEB(|0), .RSTRAMB(|0), @@ -424,14 +434,16 @@ module \$__XILINX_RAMB18_TDP2 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .WRITE_WIDTH_A(2), .WRITE_WIDTH_B(2), .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST") + .WRITE_MODE_B("READ_FIRST"), + .IS_CLKARDCLK_INVERTED(!CLKPOL2), + .IS_CLKBWRCLK_INVERTED(!CLKPOL3) ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), .DOADO(DO), .DOPADOP(DOP), .ADDRARDADDR(A1ADDR_14), - .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), + .CLKARDCLK(CLK2), .ENARDEN(|1), .REGCEAREGCE(|1), .RSTRAMARSTRAM(|0), @@ -441,7 +453,7 @@ module \$__XILINX_RAMB18_TDP2 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .DIBDI(DI), .DIPBDIP(DIP), .ADDRBWRADDR(B1ADDR_14), - .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), + .CLKBWRCLK(CLK3), .ENBWREN(|1), .REGCEB(|0), .RSTRAMB(|0), @@ -497,14 +509,16 @@ module \$__XILINX_RAMB18_TDP1 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .WRITE_WIDTH_A(1), .WRITE_WIDTH_B(1), .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST") + .WRITE_MODE_B("READ_FIRST"), + .IS_CLKARDCLK_INVERTED(!CLKPOL2), + .IS_CLKBWRCLK_INVERTED(!CLKPOL3) ) _TECHMAP_REPLACE_ ( .DIADI(16'b0), .DIPADIP(2'b0), .DOADO(DO), .DOPADOP(DOP), .ADDRARDADDR(A1ADDR_14), - .CLKARDCLK(CLKPOL2 ? CLK2 : ~CLK2), + .CLKARDCLK(CLK2), .ENARDEN(|1), .REGCEAREGCE(|1), .RSTRAMARSTRAM(|0), @@ -514,7 +528,7 @@ module \$__XILINX_RAMB18_TDP1 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN) .DIBDI(DI), .DIPBDIP(DIP), .ADDRBWRADDR(B1ADDR_14), - .CLKBWRCLK(CLKPOL3 ? CLK3 : ~CLK3), + .CLKBWRCLK(CLK3), .ENBWREN(|1), .REGCEB(|0), .RSTRAMB(|0), From 7bde74cd2a8af6b89af157b080ebe9ef1054f966 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 16 Jan 2015 15:24:54 +0100 Subject: [PATCH 302/492] Added more FF types to xilinx/cells.v --- techlibs/xilinx/cells.v | 53 ++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/techlibs/xilinx/cells.v b/techlibs/xilinx/cells.v index 75253f57b..8e5a83ce5 100644 --- a/techlibs/xilinx/cells.v +++ b/techlibs/xilinx/cells.v @@ -1,17 +1,21 @@ -module \$_DFF_P_ (D, C, Q); - input D, C; - output Q; +module \$_DFF_N_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule +module \$_DFF_P_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule - FDRE fpga_dff ( - .D(D), .Q(Q), .C(C), - .CE(1'b1), .R(1'b0) - ); +module \$_DFFE_NP_ (input D, C, E, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule +module \$_DFFE_PP_ (input D, C, E, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule -endmodule +module \$_DFF_NN0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule +module \$_DFF_NP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule +module \$_DFF_PN0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule +module \$_DFF_PP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule + +module \$_DFF_NN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule +module \$_DFF_NP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule +module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule module \$lut (A, Y); - parameter WIDTH = 0; parameter LUT = 0; @@ -19,34 +23,34 @@ module \$lut (A, Y); output Y; generate - if (WIDTH == 1) begin:lut1 - LUT1 #(.INIT(LUT)) fpga_lut (.O(Y), + if (WIDTH == 1) begin + LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0])); end else - if (WIDTH == 2) begin:lut2 - LUT2 #(.INIT(LUT)) fpga_lut (.O(Y), + if (WIDTH == 2) begin + LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1])); end else - if (WIDTH == 3) begin:lut3 - LUT3 #(.INIT(LUT)) fpga_lut (.O(Y), + if (WIDTH == 3) begin + LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2])); end else - if (WIDTH == 4) begin:lut4 - LUT4 #(.INIT(LUT)) fpga_lut (.O(Y), + if (WIDTH == 4) begin + LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3])); end else - if (WIDTH == 5) begin:lut5 - LUT5 #(.INIT(LUT)) fpga_lut (.O(Y), + if (WIDTH == 5) begin + LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]), .I4(A[4])); end else - if (WIDTH == 6) begin:lut6 - LUT6 #(.INIT(LUT)) fpga_lut (.O(Y), + if (WIDTH == 6) begin + LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]), .I4(A[4]), .I5(A[5])); end else - if (WIDTH == 7) begin:lut7 + if (WIDTH == 7) begin wire T0, T1; LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), .I0(A[0]), .I1(A[1]), .I2(A[2]), @@ -56,7 +60,7 @@ module \$lut (A, Y); .I3(A[3]), .I4(A[4]), .I5(A[5])); MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6])); end else - if (WIDTH == 8) begin:lut8 + if (WIDTH == 8) begin wire T0, T1, T2, T3, T4, T5; LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), .I0(A[0]), .I1(A[1]), .I2(A[2]), @@ -73,9 +77,8 @@ module \$lut (A, Y); MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6])); MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6])); MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7])); - end else begin:error + end else begin wire _TECHMAP_FAIL_ = 1; end endgenerate - endmodule From dff8bd3b2a94f39e6bf43620a9f147ee3788211e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 16 Jan 2015 15:49:15 +0100 Subject: [PATCH 303/492] Added dff2dffe to synth_xilinx --- techlibs/xilinx/synth_xilinx.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 380fdae73..289de4399 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -66,6 +66,7 @@ struct SynthXilinxPass : public Pass { log("\n"); log(" coarse:\n"); log(" synth -run coarse\n"); + log(" dff2dffe\n"); log("\n"); log(" bram:\n"); log(" memory_bram -rules +/xilinx/brams.txt\n"); @@ -132,6 +133,7 @@ struct SynthXilinxPass : public Pass { if (check_label(active, run_from, run_to, "coarse")) { Pass::call(design, "synth -run coarse"); + Pass::call(design, "dff2dffe"); } if (check_label(active, run_from, run_to, "bram")) From 3ed4e34380036c63d6177f41f43767b41201e4a8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 16 Jan 2015 15:50:42 +0100 Subject: [PATCH 304/492] Added cells.lib --- techlibs/common/Makefile.inc | 1 + techlibs/common/cells.lib | 108 +++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 techlibs/common/cells.lib diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index dc1e0ef66..d2ce61cf6 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -15,4 +15,5 @@ $(eval $(call add_share_file,share,techlibs/common/techmap.v)) $(eval $(call add_share_file,share,techlibs/common/blackbox.v)) $(eval $(call add_share_file,share,techlibs/common/pmux2mux.v)) $(eval $(call add_share_file,share,techlibs/common/adff2dff.v)) +$(eval $(call add_share_file,share,techlibs/common/cells.lib)) diff --git a/techlibs/common/cells.lib b/techlibs/common/cells.lib new file mode 100644 index 000000000..eb89036d7 --- /dev/null +++ b/techlibs/common/cells.lib @@ -0,0 +1,108 @@ +library(yosys_cells) { + cell(DFF_N) { + ff(IQ, IQN) { + clocked_on: "!C"; + next_state: "D"; + } + pin(D) { direction: input; } + pin(C) { direction: input; clock: true; } + pin(Q) { direction: output; function: "IQ"; } + } + cell(DFF_P) { + ff(IQ, IQN) { + clocked_on: "C"; + next_state: "D"; + } + pin(D) { direction: input; } + pin(C) { direction: input; clock: true; } + pin(Q) { direction: output; function: "IQ"; } + } + cell(DFF_NN0) { + ff(IQ, IQN) { + clocked_on: "!C"; + next_state: "D"; + clear: "!R"; + } + pin(D) { direction: input; } + pin(R) { direction: input; } + pin(C) { direction: input; clock: true; } + pin(Q) { direction: output; function: "IQ"; } + } + cell(DFF_NN1) { + ff(IQ, IQN) { + clocked_on: "!C"; + next_state: "D"; + preset: "!R"; + } + pin(D) { direction: input; } + pin(R) { direction: input; } + pin(C) { direction: input; clock: true; } + pin(Q) { direction: output; function: "IQ"; } + } + cell(DFF_NP0) { + ff(IQ, IQN) { + clocked_on: "!C"; + next_state: "D"; + clear: "R"; + } + pin(D) { direction: input; } + pin(R) { direction: input; } + pin(C) { direction: input; clock: true; } + pin(Q) { direction: output; function: "IQ"; } + } + cell(DFF_NP1) { + ff(IQ, IQN) { + clocked_on: "!C"; + next_state: "D"; + preset: "R"; + } + pin(D) { direction: input; } + pin(R) { direction: input; } + pin(C) { direction: input; clock: true; } + pin(Q) { direction: output; function: "IQ"; } + } + cell(DFF_PN0) { + ff(IQ, IQN) { + clocked_on: "C"; + next_state: "D"; + clear: "!R"; + } + pin(D) { direction: input; } + pin(R) { direction: input; } + pin(C) { direction: input; clock: true; } + pin(Q) { direction: output; function: "IQ"; } + } + cell(DFF_PN1) { + ff(IQ, IQN) { + clocked_on: "C"; + next_state: "D"; + preset: "!R"; + } + pin(D) { direction: input; } + pin(R) { direction: input; } + pin(C) { direction: input; clock: true; } + pin(Q) { direction: output; function: "IQ"; } + } + cell(DFF_PP0) { + ff(IQ, IQN) { + clocked_on: "C"; + next_state: "D"; + clear: "R"; + } + pin(D) { direction: input; } + pin(R) { direction: input; } + pin(C) { direction: input; clock: true; } + pin(Q) { direction: output; function: "IQ"; } + } + cell(DFF_PP1) { + ff(IQ, IQN) { + clocked_on: "C"; + next_state: "D"; + preset: "R"; + } + pin(D) { direction: input; } + pin(R) { direction: input; } + pin(C) { direction: input; clock: true; } + pin(Q) { direction: output; function: "IQ"; } + } +} From 8ce8a230f458d09f1847ba87a3073cf4c07579d3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 16 Jan 2015 17:51:17 +0100 Subject: [PATCH 305/492] Bugfix in dff2dffe --- passes/techmap/dff2dffe.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/dff2dffe.cc b/passes/techmap/dff2dffe.cc index 339007156..17549bd06 100644 --- a/passes/techmap/dff2dffe.cc +++ b/passes/techmap/dff2dffe.cc @@ -173,7 +173,7 @@ struct Dff2dffeWorker return or_input; RTLIL::SigSpec y = module->addWire(NEW_ID); - RTLIL::Cell *c = module->addReduceOr(NEW_ID, or_input, y); + RTLIL::Cell *c = module->addReduceAnd(NEW_ID, or_input, y); if (make_gates) { simplemap(module, c); From b32ba6f56802b7cb8bb6098ee895d4ad37438ff8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 17 Jan 2015 12:04:40 +0100 Subject: [PATCH 306/492] Optimizing no-op cell->setPort() --- kernel/rtlil.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index d396d6c24..b35cbc3d1 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1839,7 +1839,9 @@ void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) connections_[portname] = RTLIL::SigSpec(); conn_it = connections_.find(portname); log_assert(conn_it != connections_.end()); - } + } else + if (conn_it->second == signal) + return; for (auto mon : module->monitors) mon->notify_connect(this, conn_it->first, conn_it->second, signal); From 3628ca989cc70a6507dbe49de8f7230fa281e198 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 17 Jan 2015 12:05:19 +0100 Subject: [PATCH 307/492] Improved opt_muxtree --- passes/opt/opt_muxtree.cc | 42 +++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 7bdc54afa..fa91d4537 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -256,7 +256,7 @@ struct OptMuxtreeWorker list.push_back(value); } - std::vector sig2bits(RTLIL::SigSpec sig) + std::vector sig2bits(RTLIL::SigSpec sig, bool skip_non_wires = true) { std::vector results; assign_map.apply(sig); @@ -271,7 +271,8 @@ struct OptMuxtreeWorker bit2num[info.bit] = info.num; } results.push_back(bit2num[bit]); - } + } else if (!skip_non_wires) + results.push_back(-1); return results; } @@ -285,7 +286,7 @@ struct OptMuxtreeWorker // database of known active signals // the 2nd dimension is the list of or-ed signals. so we know that // for each i there is a j so that known_active[i][j] points to an - // inactive control signal. + // active control signal. std::vector> known_active; // this is just used to keep track of visited muxes in order to prohibit @@ -331,10 +332,43 @@ struct OptMuxtreeWorker } } + void replace_known(knowledge_t &knowledge, muxinfo_t &muxinfo, IdString portname) + { + SigSpec sig = muxinfo.cell->getPort(portname); + bool did_something = false; + + std::vector bits = sig2bits(sig, false); + for (int i = 0; i < GetSize(bits); i++) { + if (bits[i] < 0) + continue; + if (knowledge.known_inactive[bits[i]]) { + sig[i] = State::S0; + did_something = true; + } else { + for (auto &it : knowledge.known_active) + if (GetSize(it) == 1 && it.front() == bits[i]) { + sig[i] = State::S1; + did_something = true; + break; + } + } + } + + if (did_something) { + log(" Replacing known input bits on port %s of cell %s: %s -> %s\n", log_id(portname), + log_id(muxinfo.cell), log_signal(muxinfo.cell->getPort(portname)), log_signal(sig)); + muxinfo.cell->setPort(portname, sig); + } + } + void eval_mux(knowledge_t &knowledge, int mux_idx) { muxinfo_t &muxinfo = mux2info[mux_idx]; + // set input ports to constants if we find known active or inactive signals + replace_known(knowledge, muxinfo, "\\A"); + replace_known(knowledge, muxinfo, "\\B"); + // if there is a constant activated port we just use it for (size_t port_idx = 0; port_idx < muxinfo.ports.size()-1; port_idx++) { @@ -360,7 +394,7 @@ struct OptMuxtreeWorker } // compare ports with known_inactive and known_active signals. If all control - // signals of the port are know_inactive or if the control signals of all other + // signals of the port are known_inactive or if the control signals of all other // ports are known_active this port can't be activated. this loop includes the // default port but no known_inactive match is performed on the default port. for (size_t port_idx = 0; port_idx < muxinfo.ports.size(); port_idx++) From a95c229e12496194b513e3623ab44f9530f272ba Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 17 Jan 2015 13:56:53 +0100 Subject: [PATCH 308/492] Fixed a bug in opt_muxtree for "mux forests" --- passes/opt/opt_muxtree.cc | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index fa91d4537..33dd12a03 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -69,6 +69,8 @@ struct OptMuxtreeWorker std::vector mux2info; + std::set root_muxes; + OptMuxtreeWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module), assign_map(module), removed_count(0) { @@ -159,15 +161,26 @@ struct OptMuxtreeWorker log(" Evaluating internal representation of mux trees.\n"); - std::set root_muxes; + dict> mux_to_users; + for (auto &bi : bit2info) { + for (int i : bi.mux_drivers) + for (int j : bi.mux_users) + mux_to_users[i].insert(j); if (!bi.seen_non_mux) continue; for (int mux_idx : bi.mux_drivers) root_muxes.insert(mux_idx); } - for (int mux_idx : root_muxes) + + for (auto &it : mux_to_users) + if (GetSize(it.second) > 1) + root_muxes.insert(it.first); + + for (int mux_idx : root_muxes) { + log(" Root of a mux tree: %s\n", log_id(mux2info[mux_idx].cell)); eval_root_mux(mux_idx); + } log(" Analyzing evaluation results.\n"); @@ -317,7 +330,8 @@ struct OptMuxtreeWorker parent_muxes.push_back(m); } for (int m : parent_muxes) - eval_mux(knowledge, m); + if (!root_muxes.count(m)) + eval_mux(knowledge, m); for (int m : parent_muxes) knowledge.visited_muxes.erase(m); @@ -355,7 +369,7 @@ struct OptMuxtreeWorker } if (did_something) { - log(" Replacing known input bits on port %s of cell %s: %s -> %s\n", log_id(portname), + log(" Replacing known input bits on port %s of cell %s: %s -> %s\n", log_id(portname), log_id(muxinfo.cell), log_signal(muxinfo.cell->getPort(portname)), log_signal(sig)); muxinfo.cell->setPort(portname, sig); } From 703123114530e6010b854b5e3a5a1c0a153fa4b6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 17 Jan 2015 15:39:54 +0100 Subject: [PATCH 309/492] Added MUXCY and XORCY support to synth_xilinx --- techlibs/xilinx/Makefile.inc | 1 + techlibs/xilinx/arith.v | 91 +++++++++++++++++++++++++++++++++ techlibs/xilinx/cells_sim.v | 4 ++ techlibs/xilinx/synth_xilinx.cc | 12 ++++- 4 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 techlibs/xilinx/arith.v diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index b653660fa..646bd4c34 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -5,4 +5,5 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_sim.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams.txt)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith.v)) diff --git a/techlibs/xilinx/arith.v b/techlibs/xilinx/arith.v new file mode 100644 index 000000000..a154f7740 --- /dev/null +++ b/techlibs/xilinx/arith.v @@ -0,0 +1,91 @@ +/* + * 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. + * + */ + +(* techmap_celltype = "$lcu" *) +module _80_xilinx_lcu (P, G, CI, CO); + parameter WIDTH = 2; + + input [WIDTH-1:0] P, G; + input CI; + + output [WIDTH-1:0] CO; + + wire _TECHMAP_FAIL_ = WIDTH <= 2; + + wire [WIDTH-1:0] C = {CO, CI}; + wire [WIDTH-1:0] S = P & ~G; + + genvar i; + generate for (i = 0; i < WIDTH; i = i + 1) begin:slice + MUXCY muxcy ( + .CI(C[i]), + .DI(G[i]), + .S(S[i]), + .O(CO[i]) + ); + end endgenerate +endmodule + +(* techmap_celltype = "$alu" *) +module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] X, Y; + + input CI, BI; + output [Y_WIDTH-1:0] CO; + + wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; + + wire [Y_WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); + + wire [Y_WIDTH-1:0] AA = A_buf; + wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; + + wire [Y_WIDTH-1:0] P = AA ^ BB; + wire [Y_WIDTH-1:0] G = AA & BB; + wire [Y_WIDTH-1:0] C = {CO, CI}; + wire [Y_WIDTH-1:0] S = P & ~G; + + genvar i; + generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice + MUXCY muxcy ( + .CI(C[i]), + .DI(G[i]), + .S(S[i]), + .O(CO[i]) + ); + XORCY xorcy ( + .CI(C[i]), + .LI(S[i]), + .O(Y[i]) + ); + end endgenerate + + assign X = P; +endmodule + diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index cb290db80..138a6470f 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -1,4 +1,8 @@ +// See Xilinx UG953 and UG474 for a description of the cell types below. +// http://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdf +// http://www.xilinx.com/support/documentation/sw_manuals/xilinx2014_4/ug953-vivado-7series-libraries.pdf + module VCC(output P); assign P = 1; endmodule diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 289de4399..35bc4302e 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -73,7 +73,11 @@ struct SynthXilinxPass : public Pass { log(" techmap -map +/xilinx/brams.v\n"); log("\n"); log(" fine:\n"); - log(" synth -run fine\n"); + log(" opt -fast -full\n"); + log(" memory_map\n"); + log(" opt -full\n"); + log(" techmap -map +/techmap.v -map +/xilinx/arith.v\n"); + log(" opt -fast\n"); log("\n"); log(" map_luts:\n"); log(" abc -lut 6:8\n"); @@ -144,7 +148,11 @@ struct SynthXilinxPass : public Pass { if (check_label(active, run_from, run_to, "fine")) { - Pass::call(design, "synth -run fine"); + Pass::call(design, "opt -fast -full"); + Pass::call(design, "memory_map"); + Pass::call(design, "opt -full"); + Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith.v"); + Pass::call(design, "opt -fast"); } if (check_label(active, run_from, run_to, "map_luts")) From 8658eed52a59d5f25b734bc08e0c0a7f1497102e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 17 Jan 2015 20:46:52 +0100 Subject: [PATCH 310/492] Added support for memories to flatten (techmap) --- passes/techmap/techmap.cc | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index b1a40b25e..521ac61a0 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -153,9 +153,6 @@ struct TechmapWorker void techmap_module_worker(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl) { - if (tpl->memories.size() != 0) - log_error("Technology map yielded memories -> this is not supported.\n"); - if (tpl->processes.size() != 0) { log("Technology map yielded processes:\n"); for (auto &it : tpl->processes) @@ -176,6 +173,22 @@ struct TechmapWorker break; } + dict memory_renames; + + for (auto &it : tpl->memories) { + std::string m_name = it.first.str(); + apply_prefix(cell->name.str(), m_name); + RTLIL::Memory *m = new RTLIL::Memory; + m->name = m_name; + m->width = it.second->width; + m->start_offset = it.second->start_offset; + m->size = it.second->size; + m->attributes = it.second->attributes; + module->memories[m->name] = m; + memory_renames[it.first] = m->name; + design->select(module, m); + } + std::map positional_ports; for (auto &it : tpl->wires_) { @@ -252,6 +265,12 @@ struct TechmapWorker apply_prefix(cell->name.str(), it2.second, module); port_signal_map.apply(it2.second); } + + if (c->type == "$memrd" || c->type == "$memwr") { + IdString memid = c->getParam("\\MEMID").decode_string(); + log_assert(memory_renames.count(memid)); + c->setParam("\\MEMID", Const(memory_renames[memid].str())); + } } for (auto &it : tpl->connections()) { From 279a18c9a39fc57bfdd295511672abf49bb563ac Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 17 Jan 2015 20:47:18 +0100 Subject: [PATCH 311/492] Added synth_xilinx -retime -flatten --- techlibs/xilinx/synth_xilinx.cc | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 35bc4302e..58c6fe71b 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -58,12 +58,22 @@ struct SynthXilinxPass : public Pass { log(" from label is synonymous to 'begin', and empty to label is\n"); log(" synonymous to the end of the command list.\n"); log("\n"); + log(" -flatten\n"); + log(" flatten design before synthesis\n"); + log("\n"); + log(" -retime\n"); + log(" run 'abc' with -dff option\n"); + log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); log("\n"); log(" begin:\n"); log(" hierarchy -check -top \n"); log("\n"); + log(" flatten: (only if -flatten)\n"); + log(" proc\n"); + log(" flatten\n"); + log("\n"); log(" coarse:\n"); log(" synth -run coarse\n"); log(" dff2dffe\n"); @@ -80,7 +90,7 @@ struct SynthXilinxPass : public Pass { log(" opt -fast\n"); log("\n"); log(" map_luts:\n"); - log(" abc -lut 6:8\n"); + log(" abc -lut 5:8 [-dff]\n"); log(" clean\n"); log("\n"); log(" map_cells:\n"); @@ -97,6 +107,8 @@ struct SynthXilinxPass : public Pass { std::string arch_name = "spartan6"; std::string edif_file; std::string run_from, run_to; + bool flatten = false; + bool retime = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -117,6 +129,14 @@ struct SynthXilinxPass : public Pass { run_to = args[argidx].substr(pos+1); continue; } + if (args[argidx] == "-flatten") { + flatten = true; + continue; + } + if (args[argidx] == "-retime") { + retime = true; + continue; + } break; } extra_args(args, argidx, design); @@ -134,6 +154,12 @@ struct SynthXilinxPass : public Pass { Pass::call(design, stringf("hierarchy -check -top %s", top_module.c_str())); } + if (flatten && check_label(active, run_from, run_to, "flatten")) + { + Pass::call(design, "proc"); + Pass::call(design, "flatten"); + } + if (check_label(active, run_from, run_to, "coarse")) { Pass::call(design, "synth -run coarse"); @@ -157,7 +183,7 @@ struct SynthXilinxPass : public Pass { if (check_label(active, run_from, run_to, "map_luts")) { - Pass::call(design, "abc -lut 6:8"); + Pass::call(design, "abc -lut 5:8" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); } From 61192514e3e22e196e1df5aaaf98bb2ed6fd57df Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 18 Jan 2015 11:17:56 +0100 Subject: [PATCH 312/492] Various cleanups and improvements in opt_muxtree --- passes/opt/opt_muxtree.cc | 158 +++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 87 deletions(-) diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 33dd12a03..5a88b5a19 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -37,39 +37,33 @@ struct OptMuxtreeWorker SigMap assign_map; int removed_count; - struct bitDef_t : public std::pair { - bitDef_t() : std::pair(NULL, 0) { } - bitDef_t(const RTLIL::SigBit &bit) : std::pair(bit.wire, bit.offset) { } - }; - - struct bitinfo_t { int num; - bitDef_t bit; + SigBit bit; bool seen_non_mux; - std::vector mux_users; - std::vector mux_drivers; + vector mux_users; + vector mux_drivers; }; - std::map bit2num; - std::vector bit2info; + dict bit2num; + vector bit2info; struct portinfo_t { - std::vector ctrl_sigs; - std::vector input_sigs; - std::vector input_muxes; + int ctrl_sig; + vector input_sigs; + vector input_muxes; bool const_activated; + bool const_deactivated; bool enabled; }; struct muxinfo_t { RTLIL::Cell *cell; - std::vector ports; + vector ports; }; - std::vector mux2info; - - std::set root_muxes; + vector mux2info; + vector root_muxes; OptMuxtreeWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module), assign_map(module), removed_count(0) @@ -83,9 +77,10 @@ struct OptMuxtreeWorker // .mux_users // .mux_drivers // Populate mux2info[].ports[]: - // .ctrl_sigs + // .ctrl_sig // .input_sigs // .const_activated + // .const_deactivated for (auto cell : module->cells()) { if (cell->type == "$mux" || cell->type == "$pmux") @@ -102,13 +97,13 @@ struct OptMuxtreeWorker RTLIL::SigSpec sig = sig_b.extract(i*sig_a.size(), sig_a.size()); RTLIL::SigSpec ctrl_sig = assign_map(sig_s.extract(i, 1)); portinfo_t portinfo; + portinfo.ctrl_sig = sig2bits(ctrl_sig, false).front(); for (int idx : sig2bits(sig)) { add_to_list(bit2info[idx].mux_users, mux2info.size()); add_to_list(portinfo.input_sigs, idx); } - for (int idx : sig2bits(ctrl_sig)) - add_to_list(portinfo.ctrl_sigs, idx); portinfo.const_activated = ctrl_sig.is_fully_const() && ctrl_sig.as_bool(); + portinfo.const_deactivated = ctrl_sig.is_fully_const() && !ctrl_sig.as_bool(); portinfo.enabled = false; muxinfo.ports.push_back(portinfo); } @@ -118,7 +113,9 @@ struct OptMuxtreeWorker add_to_list(bit2info[idx].mux_users, mux2info.size()); add_to_list(portinfo.input_sigs, idx); } + portinfo.ctrl_sig = -1; portinfo.const_activated = false; + portinfo.const_deactivated = false; portinfo.enabled = false; muxinfo.ports.push_back(portinfo); @@ -162,6 +159,7 @@ struct OptMuxtreeWorker log(" Evaluating internal representation of mux trees.\n"); dict> mux_to_users; + root_muxes.resize(mux2info.size()); for (auto &bi : bit2info) { for (int i : bi.mux_drivers) @@ -170,23 +168,24 @@ struct OptMuxtreeWorker if (!bi.seen_non_mux) continue; for (int mux_idx : bi.mux_drivers) - root_muxes.insert(mux_idx); + root_muxes.at(mux_idx) = true; } for (auto &it : mux_to_users) if (GetSize(it.second) > 1) - root_muxes.insert(it.first); + root_muxes.at(it.first) = true; - for (int mux_idx : root_muxes) { - log(" Root of a mux tree: %s\n", log_id(mux2info[mux_idx].cell)); - eval_root_mux(mux_idx); - } + for (int mux_idx = 0; mux_idx < GetSize(root_muxes); mux_idx++) + if (root_muxes.at(mux_idx)) { + log(" Root of a mux tree: %s\n", log_id(mux2info[mux_idx].cell)); + eval_root_mux(mux_idx); + } log(" Analyzing evaluation results.\n"); for (auto &mi : mux2info) { - std::vector live_ports; + vector live_ports; for (int port_idx = 0; port_idx < GetSize(mi.ports); port_idx++) { portinfo_t &pi = mi.ports[port_idx]; if (pi.enabled) { @@ -247,15 +246,7 @@ struct OptMuxtreeWorker } } - bool list_is_subset(const std::vector &sub, const std::vector &super) - { - for (int v : sub) - if (!is_in_list(super, v)) - return false; - return true; - } - - bool is_in_list(const std::vector &list, int value) + bool is_in_list(const vector &list, int value) { for (int v : list) if (v == value) @@ -263,15 +254,15 @@ struct OptMuxtreeWorker return false; } - void add_to_list(std::vector &list, int value) + void add_to_list(vector &list, int value) { if (!is_in_list(list, value)) list.push_back(value); } - std::vector sig2bits(RTLIL::SigSpec sig, bool skip_non_wires = true) + vector sig2bits(RTLIL::SigSpec sig, bool skip_non_wires = true) { - std::vector results; + vector results; assign_map.apply(sig); for (auto &bit : sig) if (bit.wire != NULL) { @@ -292,57 +283,58 @@ struct OptMuxtreeWorker struct knowledge_t { // database of known inactive signals - // the 2nd integer is a reference counter used to manage the + // the payload is a reference counter used to manage the // list. when it is non-zero the signal in known to be inactive - std::map known_inactive; + vector known_inactive; // database of known active signals - // the 2nd dimension is the list of or-ed signals. so we know that - // for each i there is a j so that known_active[i][j] points to an - // active control signal. - std::vector> known_active; + vector known_active; // this is just used to keep track of visited muxes in order to prohibit // endless recursion in mux loops - std::set visited_muxes; + vector visited_muxes; }; void eval_mux_port(knowledge_t &knowledge, int mux_idx, int port_idx) { muxinfo_t &muxinfo = mux2info[mux_idx]; + + if (muxinfo.ports[port_idx].const_deactivated) + return; + muxinfo.ports[port_idx].enabled = true; - for (size_t i = 0; i < muxinfo.ports.size(); i++) { - if (int(i) == port_idx) + for (int i = 0; i < GetSize(muxinfo.ports); i++) { + if (i == port_idx) continue; - for (int b : muxinfo.ports[i].ctrl_sigs) - knowledge.known_inactive[b]++; + if (muxinfo.ports[i].ctrl_sig >= 0) + knowledge.known_inactive.at(muxinfo.ports[i].ctrl_sig)++; } if (port_idx < int(muxinfo.ports.size())-1 && !muxinfo.ports[port_idx].const_activated) - knowledge.known_active.push_back(muxinfo.ports[port_idx].ctrl_sigs); + knowledge.known_active.at(muxinfo.ports[port_idx].ctrl_sig)++; - std::vector parent_muxes; + vector parent_muxes; for (int m : muxinfo.ports[port_idx].input_muxes) { - if (knowledge.visited_muxes.count(m) > 0) + if (knowledge.visited_muxes[m]) continue; - knowledge.visited_muxes.insert(m); + knowledge.visited_muxes[m] = true; parent_muxes.push_back(m); } for (int m : parent_muxes) - if (!root_muxes.count(m)) + if (!root_muxes.at(m)) eval_mux(knowledge, m); for (int m : parent_muxes) - knowledge.visited_muxes.erase(m); + knowledge.visited_muxes[m] = false; if (port_idx < int(muxinfo.ports.size())-1 && !muxinfo.ports[port_idx].const_activated) - knowledge.known_active.pop_back(); + knowledge.known_active.at(muxinfo.ports[port_idx].ctrl_sig)--; for (size_t i = 0; i < muxinfo.ports.size(); i++) { if (int(i) == port_idx) continue; - for (int b : muxinfo.ports[i].ctrl_sigs) - knowledge.known_inactive[b]--; + if (muxinfo.ports[i].ctrl_sig >= 0) + knowledge.known_inactive.at(muxinfo.ports[i].ctrl_sig)--; } } @@ -351,20 +343,17 @@ struct OptMuxtreeWorker SigSpec sig = muxinfo.cell->getPort(portname); bool did_something = false; - std::vector bits = sig2bits(sig, false); + vector bits = sig2bits(sig, false); for (int i = 0; i < GetSize(bits); i++) { if (bits[i] < 0) continue; - if (knowledge.known_inactive[bits[i]]) { + if (knowledge.known_inactive.at(bits[i])) { sig[i] = State::S0; did_something = true; - } else { - for (auto &it : knowledge.known_active) - if (GetSize(it) == 1 && it.front() == bits[i]) { - sig[i] = State::S1; - did_something = true; - break; - } + } else + if (knowledge.known_active.at(bits[i])) { + sig[i] = State::S1; + did_something = true; } } @@ -399,16 +388,14 @@ struct OptMuxtreeWorker for (size_t port_idx = 0; port_idx < muxinfo.ports.size()-1; port_idx++) { portinfo_t &portinfo = muxinfo.ports[port_idx]; - for (size_t i = 0; i < knowledge.known_active.size(); i++) { - if (list_is_subset(knowledge.known_active[i], portinfo.ctrl_sigs)) { - eval_mux_port(knowledge, mux_idx, port_idx); - return; - } + if (knowledge.known_active.at(portinfo.ctrl_sig)) { + eval_mux_port(knowledge, mux_idx, port_idx); + return; } } - // compare ports with known_inactive and known_active signals. If all control - // signals of the port are known_inactive or if the control signals of all other + // compare ports with known_inactive and known_active signals. If the control + // signal of the port is known_inactive or if the control signals of all other // ports are known_active this port can't be activated. this loop includes the // default port but no known_inactive match is performed on the default port. for (size_t port_idx = 0; port_idx < muxinfo.ports.size(); port_idx++) @@ -417,23 +404,17 @@ struct OptMuxtreeWorker if (port_idx < muxinfo.ports.size()-1) { bool found_non_known_inactive = false; - for (int i : portinfo.ctrl_sigs) - if (knowledge.known_inactive[i] == 0) - found_non_known_inactive = true; + if (knowledge.known_inactive.at(portinfo.ctrl_sig) == 0) + found_non_known_inactive = true; if (!found_non_known_inactive) continue; } bool port_active = true; - std::vector other_ctrl_sig; for (size_t i = 0; i < muxinfo.ports.size()-1; i++) { if (i == port_idx) continue; - other_ctrl_sig.insert(other_ctrl_sig.end(), - muxinfo.ports[i].ctrl_sigs.begin(), muxinfo.ports[i].ctrl_sigs.end()); - } - for (size_t i = 0; i < knowledge.known_active.size(); i++) { - if (list_is_subset(knowledge.known_active[i], other_ctrl_sig)) + if (knowledge.known_active.at(muxinfo.ports[i].ctrl_sig)) port_active = false; } if (port_active) @@ -444,7 +425,10 @@ struct OptMuxtreeWorker void eval_root_mux(int mux_idx) { knowledge_t knowledge; - knowledge.visited_muxes.insert(mux_idx); + knowledge.known_inactive.resize(bit2info.size()); + knowledge.known_active.resize(bit2info.size()); + knowledge.visited_muxes.resize(mux2info.size()); + knowledge.visited_muxes[mux_idx] = true; eval_mux(knowledge, mux_idx); } }; @@ -464,7 +448,7 @@ struct OptMuxtreePass : public Pass { log("This pass only operates on completely selected modules without processes.\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + virtual void execute(vector args, RTLIL::Design *design) { log_header("Executing OPT_MUXTREE pass (detect dead branches in mux trees).\n"); extra_args(args, 1, design); From 0217ea0fb82b9170bb6efce734f1965ff2b181e7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 18 Jan 2015 12:12:33 +0100 Subject: [PATCH 313/492] Added hashlib::idict<> --- CodingReadme | 14 +++++++++++ kernel/hashlib.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++-- kernel/yosys.h | 1 + 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/CodingReadme b/CodingReadme index 92d54d283..78bc5a3ce 100644 --- a/CodingReadme +++ b/CodingReadme @@ -72,6 +72,20 @@ replacement for std::unordered_set. The main characteristics are: - dict and pool will have the same order of iteration across all compilers, standard libraries and architectures. +In addition to dict and pool there is also an idict that +creates a bijective map from K to the integers. For example: + + idict si; + log("%d\n", si("hello")); // will print 42 + log("%d\n", si("world")); // will print 43 + log("%d\n", si.at("world")); // will print 43 + log("%d\n", si.at("dummy")); // will throw exception + log("%s\n", si[42].c_str())); // will print hello + log("%s\n", si[43].c_str())); // will print world + log("%s\n", si[44].c_str())); // will throw exception + +It is not possible to remove elements from an idict. + 2. Standard STL data types In Yosys we use std::vector and std::string whenever applicable. When diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 72e9bc2ef..52b38a064 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -163,7 +163,11 @@ inline int hashtable_size(int min_size) throw std::length_error("hash table exceeded maximum size."); } -template> +template> class dict; +template> class idict; +template> class pool; + +template class dict { struct entry_t @@ -485,9 +489,12 @@ public: const_iterator end() const { return const_iterator(nullptr, -1); } }; -template> +template class pool { + template friend class idict; + +protected: struct entry_t { K udata; @@ -783,6 +790,55 @@ public: const_iterator end() const { return const_iterator(nullptr, -1); } }; +template +class idict +{ + pool database; + +public: + typedef typename pool::const_iterator const_iterator; + + int operator()(const K &key) + { + int hash = database.do_hash(key); + int i = database.do_lookup(key, hash); + if (i < 0) + i = database.do_insert(key, hash); + return i + offset; + } + + int at(const K &key) const + { + int hash = database.do_hash(key); + int i = database.do_lookup(key, hash); + if (i < 0) + throw std::out_of_range("idict::at()"); + return i + offset; + } + + int count(const K &key) const + { + int hash = database.do_hash(key); + int i = database.do_lookup(key, hash); + return i < 0 ? 0 : 1; + } + + void expect(const K &key, int i) + { + int j = (*this)(key); + if (i != j) + throw std::out_of_range("idict::expect()"); + } + + const K &operator[](int index) const + { + return database.entries.at(index - offset).udata; + } + + const_iterator begin() const { return database.begin(); } + const_iterator end() const { return database.end(); } +}; + } /* namespace hashlib */ #endif diff --git a/kernel/yosys.h b/kernel/yosys.h index d1e01b19c..a6f4cb665 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -148,6 +148,7 @@ using hashlib::hash_cstr_ops; using hashlib::hash_ptr_ops; using hashlib::hash_obj_ops; using hashlib::dict; +using hashlib::idict; using hashlib::pool; namespace RTLIL { From d3b35017f8acc862aeab7e7b67bfb1063e6bcd2a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 18 Jan 2015 12:13:18 +0100 Subject: [PATCH 314/492] More opt_muxtree cleanups --- passes/opt/opt_muxtree.cc | 108 ++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 64 deletions(-) diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 5a88b5a19..0bf312a48 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -38,20 +38,18 @@ struct OptMuxtreeWorker int removed_count; struct bitinfo_t { - int num; - SigBit bit; bool seen_non_mux; - vector mux_users; - vector mux_drivers; + pool mux_users; + pool mux_drivers; }; - dict bit2num; + idict bit2num; vector bit2info; struct portinfo_t { int ctrl_sig; - vector input_sigs; - vector input_muxes; + pool input_sigs; + pool input_muxes; bool const_activated; bool const_deactivated; bool enabled; @@ -93,14 +91,14 @@ struct OptMuxtreeWorker muxinfo_t muxinfo; muxinfo.cell = cell; - for (int i = 0; i < sig_s.size(); i++) { - RTLIL::SigSpec sig = sig_b.extract(i*sig_a.size(), sig_a.size()); + for (int i = 0; i < GetSize(sig_s); i++) { + RTLIL::SigSpec sig = sig_b.extract(i*GetSize(sig_a), GetSize(sig_a)); RTLIL::SigSpec ctrl_sig = assign_map(sig_s.extract(i, 1)); portinfo_t portinfo; portinfo.ctrl_sig = sig2bits(ctrl_sig, false).front(); for (int idx : sig2bits(sig)) { - add_to_list(bit2info[idx].mux_users, mux2info.size()); - add_to_list(portinfo.input_sigs, idx); + bit2info[idx].mux_users.insert(GetSize(mux2info)); + portinfo.input_sigs.insert(idx); } portinfo.const_activated = ctrl_sig.is_fully_const() && ctrl_sig.as_bool(); portinfo.const_deactivated = ctrl_sig.is_fully_const() && !ctrl_sig.as_bool(); @@ -110,8 +108,8 @@ struct OptMuxtreeWorker portinfo_t portinfo; for (int idx : sig2bits(sig_a)) { - add_to_list(bit2info[idx].mux_users, mux2info.size()); - add_to_list(portinfo.input_sigs, idx); + bit2info[idx].mux_users.insert(GetSize(mux2info)); + portinfo.input_sigs.insert(idx); } portinfo.ctrl_sig = -1; portinfo.const_activated = false; @@ -120,7 +118,7 @@ struct OptMuxtreeWorker muxinfo.ports.push_back(portinfo); for (int idx : sig2bits(sig_y)) - add_to_list(bit2info[idx].mux_drivers, mux2info.size()); + bit2info[idx].mux_drivers.insert(GetSize(mux2info)); for (int idx : sig2bits(sig_s)) bit2info[idx].seen_non_mux = true; @@ -141,25 +139,25 @@ struct OptMuxtreeWorker bit2info[idx].seen_non_mux = true; } - if (mux2info.size() == 0) { + if (mux2info.empty()) { log(" No muxes found in this module.\n"); return; } // Populate mux2info[].ports[]: // .input_muxes - for (size_t i = 0; i < bit2info.size(); i++) + for (int i = 0; i < GetSize(bit2info); i++) for (int j : bit2info[i].mux_users) for (auto &p : mux2info[j].ports) { - if (is_in_list(p.input_sigs, i)) + if (p.input_sigs.count(i)) for (int k : bit2info[i].mux_drivers) - add_to_list(p.input_muxes, k); + p.input_muxes.insert(k); } log(" Evaluating internal representation of mux trees.\n"); dict> mux_to_users; - root_muxes.resize(mux2info.size()); + root_muxes.resize(GetSize(mux2info)); for (auto &bi : bit2info) { for (int i : bi.mux_drivers) @@ -197,10 +195,10 @@ struct OptMuxtreeWorker } } - if (live_ports.size() == mi.ports.size()) + if (GetSize(live_ports) == GetSize(mi.ports)) continue; - if (live_ports.size() == 0) { + if (live_ports.empty()) { module->remove(mi.cell); continue; } @@ -213,9 +211,9 @@ struct OptMuxtreeWorker RTLIL::SigSpec sig_ports = sig_b; sig_ports.append(sig_a); - if (live_ports.size() == 1) + if (GetSize(live_ports) == 1) { - RTLIL::SigSpec sig_in = sig_ports.extract(live_ports[0]*sig_a.size(), sig_a.size()); + RTLIL::SigSpec sig_in = sig_ports.extract(live_ports[0]*GetSize(sig_a), GetSize(sig_a)); module->connect(RTLIL::SigSig(sig_y, sig_in)); module->remove(mi.cell); } @@ -223,9 +221,9 @@ struct OptMuxtreeWorker { RTLIL::SigSpec new_sig_a, new_sig_b, new_sig_s; - for (size_t i = 0; i < live_ports.size(); i++) { - RTLIL::SigSpec sig_in = sig_ports.extract(live_ports[i]*sig_a.size(), sig_a.size()); - if (i == live_ports.size()-1) { + for (int i = 0; i < GetSize(live_ports); i++) { + RTLIL::SigSpec sig_in = sig_ports.extract(live_ports[i]*GetSize(sig_a), GetSize(sig_a)); + if (i == GetSize(live_ports)-1) { new_sig_a = sig_in; } else { new_sig_b.append(sig_in); @@ -236,30 +234,16 @@ struct OptMuxtreeWorker mi.cell->setPort("\\A", new_sig_a); mi.cell->setPort("\\B", new_sig_b); mi.cell->setPort("\\S", new_sig_s); - if (new_sig_s.size() == 1) { + if (GetSize(new_sig_s) == 1) { mi.cell->type = "$mux"; mi.cell->parameters.erase("\\S_WIDTH"); } else { - mi.cell->parameters["\\S_WIDTH"] = RTLIL::Const(new_sig_s.size()); + mi.cell->parameters["\\S_WIDTH"] = RTLIL::Const(GetSize(new_sig_s)); } } } } - bool is_in_list(const vector &list, int value) - { - for (int v : list) - if (v == value) - return true; - return false; - } - - void add_to_list(vector &list, int value) - { - if (!is_in_list(list, value)) - list.push_back(value); - } - vector sig2bits(RTLIL::SigSpec sig, bool skip_non_wires = true) { vector results; @@ -268,13 +252,11 @@ struct OptMuxtreeWorker if (bit.wire != NULL) { if (bit2num.count(bit) == 0) { bitinfo_t info; - info.num = bit2info.size(); - info.bit = bit; info.seen_non_mux = false; + bit2num.expect(bit, GetSize(bit2info)); bit2info.push_back(info); - bit2num[info.bit] = info.num; } - results.push_back(bit2num[bit]); + results.push_back(bit2num.at(bit)); } else if (!skip_non_wires) results.push_back(-1); return results; @@ -311,7 +293,7 @@ struct OptMuxtreeWorker knowledge.known_inactive.at(muxinfo.ports[i].ctrl_sig)++; } - if (port_idx < int(muxinfo.ports.size())-1 && !muxinfo.ports[port_idx].const_activated) + if (port_idx < GetSize(muxinfo.ports)-1 && !muxinfo.ports[port_idx].const_activated) knowledge.known_active.at(muxinfo.ports[port_idx].ctrl_sig)++; vector parent_muxes; @@ -327,11 +309,11 @@ struct OptMuxtreeWorker for (int m : parent_muxes) knowledge.visited_muxes[m] = false; - if (port_idx < int(muxinfo.ports.size())-1 && !muxinfo.ports[port_idx].const_activated) + if (port_idx < GetSize(muxinfo.ports)-1 && !muxinfo.ports[port_idx].const_activated) knowledge.known_active.at(muxinfo.ports[port_idx].ctrl_sig)--; - for (size_t i = 0; i < muxinfo.ports.size(); i++) { - if (int(i) == port_idx) + for (int i = 0; i < GetSize(muxinfo.ports); i++) { + if (i == port_idx) continue; if (muxinfo.ports[i].ctrl_sig >= 0) knowledge.known_inactive.at(muxinfo.ports[i].ctrl_sig)--; @@ -373,7 +355,7 @@ struct OptMuxtreeWorker replace_known(knowledge, muxinfo, "\\B"); // if there is a constant activated port we just use it - for (size_t port_idx = 0; port_idx < muxinfo.ports.size()-1; port_idx++) + for (int port_idx = 0; port_idx < GetSize(muxinfo.ports); port_idx++) { portinfo_t &portinfo = muxinfo.ports[port_idx]; if (portinfo.const_activated) { @@ -385,7 +367,7 @@ struct OptMuxtreeWorker // compare ports with known_active signals. if we find a match, only this // port can be active. do not include the last port (its the default port // that has no control signals). - for (size_t port_idx = 0; port_idx < muxinfo.ports.size()-1; port_idx++) + for (int port_idx = 0; port_idx < GetSize(muxinfo.ports)-1; port_idx++) { portinfo_t &portinfo = muxinfo.ports[port_idx]; if (knowledge.known_active.at(portinfo.ctrl_sig)) { @@ -398,11 +380,11 @@ struct OptMuxtreeWorker // signal of the port is known_inactive or if the control signals of all other // ports are known_active this port can't be activated. this loop includes the // default port but no known_inactive match is performed on the default port. - for (size_t port_idx = 0; port_idx < muxinfo.ports.size(); port_idx++) + for (int port_idx = 0; port_idx < GetSize(muxinfo.ports); port_idx++) { portinfo_t &portinfo = muxinfo.ports[port_idx]; - if (port_idx < muxinfo.ports.size()-1) { + if (port_idx < GetSize(muxinfo.ports)-1) { bool found_non_known_inactive = false; if (knowledge.known_inactive.at(portinfo.ctrl_sig) == 0) found_non_known_inactive = true; @@ -411,7 +393,7 @@ struct OptMuxtreeWorker } bool port_active = true; - for (size_t i = 0; i < muxinfo.ports.size()-1; i++) { + for (int i = 0; i < GetSize(muxinfo.ports)-1; i++) { if (i == port_idx) continue; if (knowledge.known_active.at(muxinfo.ports[i].ctrl_sig)) @@ -425,9 +407,9 @@ struct OptMuxtreeWorker void eval_root_mux(int mux_idx) { knowledge_t knowledge; - knowledge.known_inactive.resize(bit2info.size()); - knowledge.known_active.resize(bit2info.size()); - knowledge.visited_muxes.resize(mux2info.size()); + knowledge.known_inactive.resize(GetSize(bit2info)); + knowledge.known_active.resize(GetSize(bit2info)); + knowledge.visited_muxes.resize(GetSize(mux2info)); knowledge.visited_muxes[mux_idx] = true; eval_mux(knowledge, mux_idx); } @@ -460,12 +442,10 @@ struct OptMuxtreePass : public Pass { log("Skipping module %s as it is only partially selected.\n", log_id(mod)); continue; } - if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); - } else { - OptMuxtreeWorker worker(design, mod); - total_count += worker.removed_count; - } + if (mod->has_processes_warn()) + continue; + OptMuxtreeWorker worker(design, mod); + total_count += worker.removed_count; } if (total_count) design->scratchpad_set_bool("opt.did_something", true); From f630868bc992d0c26b38a7e48933545b461249f1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 18 Jan 2015 12:57:36 +0100 Subject: [PATCH 315/492] Improvements in opt_muxtree --- passes/opt/opt_muxtree.cc | 85 +++++++++++++++++++++++---------------- tests/simple/muxtree.v | 8 ++++ 2 files changed, 58 insertions(+), 35 deletions(-) diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 0bf312a48..ae5fe57e5 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -62,6 +62,7 @@ struct OptMuxtreeWorker vector mux2info; vector root_muxes; + vector root_enable_muxes; OptMuxtreeWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module), assign_map(module), removed_count(0) @@ -158,6 +159,7 @@ struct OptMuxtreeWorker dict> mux_to_users; root_muxes.resize(GetSize(mux2info)); + root_enable_muxes.resize(GetSize(mux2info)); for (auto &bi : bit2info) { for (int i : bi.mux_drivers) @@ -165,8 +167,10 @@ struct OptMuxtreeWorker mux_to_users[i].insert(j); if (!bi.seen_non_mux) continue; - for (int mux_idx : bi.mux_drivers) + for (int mux_idx : bi.mux_drivers) { root_muxes.at(mux_idx) = true; + root_enable_muxes.at(mux_idx) = true; + } } for (auto &it : mux_to_users) @@ -277,14 +281,12 @@ struct OptMuxtreeWorker vector visited_muxes; }; - void eval_mux_port(knowledge_t &knowledge, int mux_idx, int port_idx) + void eval_mux_port(knowledge_t &knowledge, int mux_idx, int port_idx, bool do_replace_known, bool do_enable_ports) { muxinfo_t &muxinfo = mux2info[mux_idx]; - if (muxinfo.ports[port_idx].const_deactivated) - return; - - muxinfo.ports[port_idx].enabled = true; + if (do_enable_ports) + muxinfo.ports[port_idx].enabled = true; for (int i = 0; i < GetSize(muxinfo.ports); i++) { if (i == port_idx) @@ -304,8 +306,10 @@ struct OptMuxtreeWorker parent_muxes.push_back(m); } for (int m : parent_muxes) - if (!root_muxes.at(m)) - eval_mux(knowledge, m); + if (root_muxes.at(m)) + eval_mux(knowledge, m, false, do_enable_ports); + else + eval_mux(knowledge, m, do_replace_known, do_enable_ports); for (int m : parent_muxes) knowledge.visited_muxes[m] = false; @@ -325,6 +329,14 @@ struct OptMuxtreeWorker SigSpec sig = muxinfo.cell->getPort(portname); bool did_something = false; + int width = 0; + idict ctrl_bits; + if (portname == "\\B") + width = GetSize(muxinfo.cell->getPort("\\A")); + for (int bit : sig2bits(muxinfo.cell->getPort("\\S"), false)) + ctrl_bits(bit); + + int port_idx = 0, port_off = 0; vector bits = sig2bits(sig, false); for (int i = 0; i < GetSize(bits); i++) { if (bits[i] < 0) @@ -337,6 +349,19 @@ struct OptMuxtreeWorker sig[i] = State::S1; did_something = true; } + if (width) { + if (ctrl_bits.count(bits[i])) { + sig[i] = ctrl_bits.at(bits[i]) == port_idx ? State::S1 : State::S0; + did_something = true; + } + if (++port_off == width) + port_idx++, port_off=0; + } else { + if (ctrl_bits.count(bits[i])) { + sig[i] = State::S0; + did_something = true; + } + } } if (did_something) { @@ -346,20 +371,22 @@ struct OptMuxtreeWorker } } - void eval_mux(knowledge_t &knowledge, int mux_idx) + void eval_mux(knowledge_t &knowledge, int mux_idx, bool do_replace_known, bool do_enable_ports) { muxinfo_t &muxinfo = mux2info[mux_idx]; // set input ports to constants if we find known active or inactive signals - replace_known(knowledge, muxinfo, "\\A"); - replace_known(knowledge, muxinfo, "\\B"); + if (do_replace_known) { + replace_known(knowledge, muxinfo, "\\A"); + replace_known(knowledge, muxinfo, "\\B"); + } // if there is a constant activated port we just use it for (int port_idx = 0; port_idx < GetSize(muxinfo.ports); port_idx++) { portinfo_t &portinfo = muxinfo.ports[port_idx]; if (portinfo.const_activated) { - eval_mux_port(knowledge, mux_idx, port_idx); + eval_mux_port(knowledge, mux_idx, port_idx, do_replace_known, do_enable_ports); return; } } @@ -370,37 +397,25 @@ struct OptMuxtreeWorker for (int port_idx = 0; port_idx < GetSize(muxinfo.ports)-1; port_idx++) { portinfo_t &portinfo = muxinfo.ports[port_idx]; + if (portinfo.const_deactivated) + continue; if (knowledge.known_active.at(portinfo.ctrl_sig)) { - eval_mux_port(knowledge, mux_idx, port_idx); + eval_mux_port(knowledge, mux_idx, port_idx, do_replace_known, do_enable_ports); return; } } - // compare ports with known_inactive and known_active signals. If the control - // signal of the port is known_inactive or if the control signals of all other - // ports are known_active this port can't be activated. this loop includes the - // default port but no known_inactive match is performed on the default port. + // eval all ports that could be activated (control signal is not in + // known_inactive or const_deactivated). for (int port_idx = 0; port_idx < GetSize(muxinfo.ports); port_idx++) { portinfo_t &portinfo = muxinfo.ports[port_idx]; - - if (port_idx < GetSize(muxinfo.ports)-1) { - bool found_non_known_inactive = false; - if (knowledge.known_inactive.at(portinfo.ctrl_sig) == 0) - found_non_known_inactive = true; - if (!found_non_known_inactive) + if (portinfo.const_deactivated) + continue; + if (port_idx < GetSize(muxinfo.ports)-1) + if (knowledge.known_inactive.at(portinfo.ctrl_sig)) continue; - } - - bool port_active = true; - for (int i = 0; i < GetSize(muxinfo.ports)-1; i++) { - if (i == port_idx) - continue; - if (knowledge.known_active.at(muxinfo.ports[i].ctrl_sig)) - port_active = false; - } - if (port_active) - eval_mux_port(knowledge, mux_idx, port_idx); + eval_mux_port(knowledge, mux_idx, port_idx, do_replace_known, do_enable_ports); } } @@ -411,7 +426,7 @@ struct OptMuxtreeWorker knowledge.known_active.resize(GetSize(bit2info)); knowledge.visited_muxes.resize(GetSize(mux2info)); knowledge.visited_muxes[mux_idx] = true; - eval_mux(knowledge, mux_idx); + eval_mux(knowledge, mux_idx, true, root_enable_muxes.at(mux_idx)); } }; diff --git a/tests/simple/muxtree.v b/tests/simple/muxtree.v index c5060eae9..46c78d4cf 100644 --- a/tests/simple/muxtree.v +++ b/tests/simple/muxtree.v @@ -70,3 +70,11 @@ end endmodule + +// test case for muxtree with select on leaves + +module select_leaves(input C, D, output reg Q); + always @(posedge C) + Q <= Q ? Q : D ? 1'b1 : Q; +endmodule + From 694cc01f1de8e0d7db7c5e03cb93796430c6ca5b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 18 Jan 2015 13:24:01 +0100 Subject: [PATCH 316/492] improvements in muxtree/select_leaves test --- tests/simple/muxtree.v | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/simple/muxtree.v b/tests/simple/muxtree.v index 46c78d4cf..1fb1cea5e 100644 --- a/tests/simple/muxtree.v +++ b/tests/simple/muxtree.v @@ -73,8 +73,11 @@ endmodule // test case for muxtree with select on leaves -module select_leaves(input C, D, output reg Q); +module select_leaves(input R, C, D, output reg Q); always @(posedge C) - Q <= Q ? Q : D ? 1'b1 : Q; + if (!R) + Q <= R; + else + Q <= Q ? Q : D ? D : Q; endmodule From 026b94a6f10525be7f3f8d354f4b9889aacef605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Schm=C3=B6lzer?= Date: Sun, 18 Jan 2015 16:09:42 +0100 Subject: [PATCH 317/492] Add "echo-yosys-ver" and "echo-git-rev" Makefile targets. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These Makefile targets simply echo the corresponding Makefile variable, simplifying package build scripts. Signed-off-by: Martin Schmölzer --- Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile b/Makefile index a1e2cb76b..278ad8811 100644 --- a/Makefile +++ b/Makefile @@ -385,6 +385,12 @@ config-gprof: clean config-sudo: echo "INSTALL_SUDO := sudo" >> Makefile.conf +echo-yosys-ver: + @echo "$(YOSYS_VER)" + +echo-git-rev: + @echo "$(GIT_REV)" + -include libs/*/*.d -include frontends/*/*.d -include passes/*/*.d From 8d295730e568421d3dc5b0779bd90d826e874254 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 18 Jan 2015 19:05:29 +0100 Subject: [PATCH 318/492] Refactoring of memory_bram and xilinx brams --- passes/memory/memory_bram.cc | 669 +++++++++++++++++++++------------ techlibs/xilinx/brams.txt | 116 ++---- techlibs/xilinx/brams.v | 399 ++------------------ techlibs/xilinx/tests/bram1.sh | 10 +- tests/bram/generate.py | 4 +- tests/tools/cmp_tbdata.c | 2 + 6 files changed, 496 insertions(+), 704 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index b212e92ed..954c2ff7c 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -31,47 +31,111 @@ struct rules_t SigBit sig_clock; SigSpec sig_addr, sig_data, sig_en; bool effective_clkpol; + bool make_transp; int mapped_port; }; struct bram_t { IdString name; + int variant; + int groups, abits, dbits, init; vector ports, wrmode, enable, transp, clocks, clkpol; + void dump_config() const + { + log(" bram %s # variant %d\n", log_id(name), variant); + log(" init %d\n", init); + log(" abits %d\n", abits); + log(" dbits %d\n", dbits); + log(" groups %d\n", groups); + + log(" ports "); for (int v : ports) log("%4d", v); log("\n"); + log(" wrmode"); for (int v : wrmode) log("%4d", v); log("\n"); + log(" enable"); for (int v : enable) log("%4d", v); log("\n"); + log(" transp"); for (int v : transp) log("%4d", v); log("\n"); + log(" clocks"); for (int v : clocks) log("%4d", v); log("\n"); + log(" clkpol"); for (int v : clkpol) log("%4d", v); log("\n"); + log(" endbram\n"); + } + + void check_vectors() const + { + if (groups != GetSize(ports)) log_error("Bram %s variant %d has %d groups but only %d entries in 'ports'.\n", log_id(name), variant, groups, GetSize(ports)); + if (groups != GetSize(wrmode)) log_error("Bram %s variant %d has %d groups but only %d entries in 'wrmode'.\n", log_id(name), variant, groups, GetSize(wrmode)); + if (groups != GetSize(enable)) log_error("Bram %s variant %d has %d groups but only %d entries in 'enable'.\n", log_id(name), variant, groups, GetSize(enable)); + if (groups != GetSize(transp)) log_error("Bram %s variant %d has %d groups but only %d entries in 'transp'.\n", log_id(name), variant, groups, GetSize(transp)); + if (groups != GetSize(clocks)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clocks'.\n", log_id(name), variant, groups, GetSize(clocks)); + if (groups != GetSize(clkpol)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clkpol'.\n", log_id(name), variant, groups, GetSize(clkpol)); + } + vector make_portinfos() const { vector portinfos; - for (int i = 0; i < groups && i < GetSize(ports); i++) + for (int i = 0; i < groups; i++) for (int j = 0; j < ports[i]; j++) { portinfo_t pi; pi.group = i; pi.index = j; pi.dupidx = 0; - pi.wrmode = i < GetSize(wrmode) ? wrmode[i] : 0; - pi.enable = i < GetSize(enable) ? enable[i] : 0; - pi.transp = i < GetSize(transp) ? transp[i] : 0; - pi.clocks = i < GetSize(clocks) ? clocks[i] : 0; - pi.clkpol = i < GetSize(clkpol) ? clkpol[i] : 0; + pi.wrmode = wrmode[i]; + pi.enable = enable[i]; + pi.transp = transp[i]; + pi.clocks = clocks[i]; + pi.clkpol = clkpol[i]; pi.mapped_port = -1; + pi.make_transp = false; + pi.effective_clkpol = false; portinfos.push_back(pi); } return portinfos; } + + void find_variant_params(dict &variant_params, const bram_t &other) const + { + log_assert(name == other.name); + + if (groups != other.groups) + log_error("Bram %s variants %d and %d have different values for 'groups'.\n", log_id(name), variant, other.variant); + + if (abits != other.abits) + variant_params["\\CFG_ABITS"] = abits; + if (dbits != other.dbits) + variant_params["\\CFG_DBITS"] = dbits; + if (init != other.init) + variant_params["\\CFG_INIT"] = init; + + for (int i = 0; i < groups; i++) + { + if (ports[i] != other.ports[i]) + log_error("Bram %s variants %d and %d have different number of %c-ports.\n", log_id(name), variant, other.variant, 'A'+i); + if (wrmode[i] != other.wrmode[i]) + variant_params[stringf("\\CFG_WRMODE_%c", 'A' + i)] = wrmode[1]; + if (enable[i] != other.enable[i]) + variant_params[stringf("\\CFG_ENABLE_%c", 'A' + i)] = enable[1]; + if (transp[i] != other.transp[i]) + variant_params[stringf("\\CFG_TRANSP_%c", 'A' + i)] = transp[1]; + if (clocks[i] != other.clocks[i]) + variant_params[stringf("\\CFG_CLOCKS_%c", 'A' + i)] = clocks[1]; + if (clkpol[i] != other.clkpol[i]) + variant_params[stringf("\\CFG_CLKPOL_%c", 'A' + i)] = clkpol[1]; + } + } }; struct match_t { IdString name; dict min_limits, max_limits; - bool or_next_if_better; - int shuffle_enable; + bool or_next_if_better, make_transp; + char shuffle_enable; }; - dict brams; + dict> brams; vector matches; std::ifstream infile; vector tokens; + vector labels; int linecount; void syntax_error() @@ -83,11 +147,16 @@ struct rules_t bool next_line() { - linecount++; - tokens.clear(); string line; while (std::getline(infile, line)) { + tokens.clear(); + labels.clear(); + linecount++; for (string tok = next_token(line); !tok.empty(); tok = next_token(line)) { + if (tok[0] == '@') { + labels.push_back(tok.substr(1)); + continue; + } if (tok[0] == '#') break; tokens.push_back(tok); @@ -120,53 +189,83 @@ struct rules_t void parse_bram() { + IdString bram_name = RTLIL::escape_id(tokens[1]); + if (GetSize(tokens) != 2) syntax_error(); - bram_t data; - data.name = RTLIL::escape_id(tokens[1]); + vector> lines_nolabels; + std::map>> lines_labels; while (next_line()) { - if (GetSize(tokens) == 1 && tokens[0] == "endbram") { - brams[data.name] = data; - return; - } - - if (parse_single_int("groups", data.groups)) - continue; - - if (parse_single_int("abits", data.abits)) - continue; - - if (parse_single_int("dbits", data.dbits)) - continue; - - if (parse_single_int("init", data.init)) - continue; - - if (parse_int_vect("ports", data.ports)) - continue; - - if (parse_int_vect("wrmode", data.wrmode)) - continue; - - if (parse_int_vect("enable", data.enable)) - continue; - - if (parse_int_vect("transp", data.transp)) - continue; - - if (parse_int_vect("clocks", data.clocks)) - continue; - - if (parse_int_vect("clkpol", data.clkpol)) - continue; - - break; + if (GetSize(tokens) == 1 && tokens[0] == "endbram") + break; + if (labels.empty()) + lines_nolabels.push_back(tokens); + for (auto lab : labels) + lines_labels[lab].push_back(tokens); } - syntax_error(); + std::map>> variant_lines; + + if (lines_labels.empty()) + variant_lines[""] = lines_nolabels; + for (auto &it : lines_labels) { + variant_lines[it.first] = lines_nolabels; + variant_lines[it.first].insert(variant_lines[it.first].end(), it.second.begin(), it.second.end()); + } + + for (auto &it : variant_lines) + { + bram_t data; + data.name = bram_name; + data.variant = GetSize(brams[data.name]) + 1; + data.groups = 0; + data.abits = 0; + data.dbits = 0; + data.init = 0; + + for (auto &line_tokens : it.second) + { + tokens = line_tokens; + + if (parse_single_int("groups", data.groups)) + continue; + + if (parse_single_int("abits", data.abits)) + continue; + + if (parse_single_int("dbits", data.dbits)) + continue; + + if (parse_single_int("init", data.init)) + continue; + + if (parse_int_vect("ports", data.ports)) + continue; + + if (parse_int_vect("wrmode", data.wrmode)) + continue; + + if (parse_int_vect("enable", data.enable)) + continue; + + if (parse_int_vect("transp", data.transp)) + continue; + + if (parse_int_vect("clocks", data.clocks)) + continue; + + if (parse_int_vect("clkpol", data.clkpol)) + continue; + + syntax_error(); + } + + data.check_vectors(); + brams[data.name].push_back(data); + } } void parse_match() @@ -177,13 +276,17 @@ struct rules_t match_t data; data.name = RTLIL::escape_id(tokens[1]); data.or_next_if_better = false; + data.make_transp = false; data.shuffle_enable = 0; while (next_line()) { + if (!labels.empty()) + syntax_error(); + if (GetSize(tokens) == 1 && tokens[0] == "endmatch") { matches.push_back(data); - return; + break; } if (GetSize(tokens) == 3 && tokens[0] == "min") { @@ -196,8 +299,13 @@ struct rules_t continue; } - if (GetSize(tokens) == 2 && tokens[0] == "shuffle_enable") { - data.shuffle_enable = atoi(tokens[1].c_str()); + if (GetSize(tokens) == 2 && tokens[0] == "shuffle_enable" && GetSize(tokens[1]) == 1 && 'A' <= tokens[1][0] && tokens[1][0] <= 'Z') { + data.shuffle_enable = tokens[1][0]; + continue; + } + + if (GetSize(tokens) == 1 && tokens[0] == "make_transp") { + data.make_transp = true; continue; } @@ -206,10 +314,8 @@ struct rules_t continue; } - break; + syntax_error(); } - - syntax_error(); } void parse(string filename) @@ -225,22 +331,37 @@ struct rules_t while (next_line()) { - if (tokens[0] == "bram") parse_bram(); - else if (tokens[0] == "match") parse_match(); - else syntax_error(); + if (!labels.empty()) + syntax_error(); + + if (tokens[0] == "bram") { + parse_bram(); + continue; + } + + if (tokens[0] == "match") { + parse_match(); + continue; + } + + syntax_error(); } infile.close(); } }; -bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_t &match, dict &match_properties, int mode) +bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram, const rules_t::match_t &match, dict &match_properties, int mode) { Module *module = cell->module; auto portinfos = bram.make_portinfos(); int dup_count = 1; + pair make_transp_clk; + bool enable_make_transp = false; + int make_transp_enbits = 0; + dict> clock_domains; dict clock_polarities; dict read_transp; @@ -264,7 +385,8 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ transp_max = std::max(transp_max, pi.transp); } - log(" Mapping to bram type %s:\n", log_id(bram.name)); + log(" Mapping to bram type %s (variant %d):\n", log_id(bram.name), bram.variant); + // bram.dump_config(); int mem_size = cell->getParam("\\SIZE").as_int(); int mem_abits = cell->getParam("\\ABITS").as_int(); @@ -294,9 +416,9 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ SigSpec rd_data = cell->getPort("\\RD_DATA"); SigSpec rd_addr = cell->getPort("\\RD_ADDR"); - if (match.shuffle_enable && bram.dbits >= match.shuffle_enable*2) + if (match.shuffle_enable && bram.dbits >= portinfos.at(match.shuffle_enable - 'A').enable*2 && portinfos.at(match.shuffle_enable - 'A').enable > 0) { - int bucket_size = bram.dbits / match.shuffle_enable; + int bucket_size = bram.dbits / portinfos.at(match.shuffle_enable - 'A').enable; log(" Shuffle bit order to accommodate enable buckets of size %d..\n", bucket_size); // extract unshuffled data/enable bits @@ -403,6 +525,8 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ for (; bram_port_i < GetSize(portinfos); bram_port_i++) { auto &pi = portinfos[bram_port_i]; + make_transp_enbits = pi.enable; + make_transp_clk = clkdom; if (pi.wrmode != 1) skip_bram_wport: @@ -544,8 +668,13 @@ grow_read_ports:; goto skip_bram_rport; } if (read_transp.count(pi.transp) && read_transp.at(pi.transp) != transp) { - log(" Bram port %c%d.%d has incompatible read transparancy.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); - goto skip_bram_rport; + if (match.make_transp && wr_ports <= 1) { + pi.make_transp = true; + enable_make_transp = true; + } else { + log(" Bram port %c%d.%d has incompatible read transparancy.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + goto skip_bram_rport; + } } } else { if (pi.clocks != 0) { @@ -595,6 +724,10 @@ grow_read_ports:; int cells = ((mem_width + bram.dbits - 1) / bram.dbits) * ((mem_size + (1 << bram.abits) - 1) / (1 << bram.abits)); match_properties["efficiency"] = (100 * match_properties["bits"]) / (dup_count * cells * bram.dbits * (1 << bram.abits)); + match_properties["dcells"] = ((mem_width + bram.dbits - 1) / bram.dbits); + match_properties["acells"] = ((mem_size + (1 << bram.abits) - 1) / (1 << bram.abits)); + match_properties["cells"] = match_properties["dcells"] * match_properties["acells"] * match_properties["dups"]; + log(" Updated properties: dups=%d waste=%d efficiency=%d\n", match_properties["dups"], match_properties["waste"], match_properties["efficiency"]); @@ -623,81 +756,130 @@ grow_read_ports:; return true; } + // prepare variant parameters + + dict variant_params; + for (auto &other_bram : rules.brams.at(bram.name)) + bram.find_variant_params(variant_params, other_bram); + // actually replace that memory cell dict> dout_cache; for (int grid_d = 0; grid_d*bram.dbits < mem_width; grid_d++) - for (int grid_a = 0; grid_a*(1 << bram.abits) < mem_size; grid_a++) - for (int dupidx = 0; dupidx < dup_count; dupidx++) { - Cell *c = module->addCell(module->uniquify(stringf("%s.%d.%d.%d", cell->name.c_str(), grid_d, grid_a, dupidx)), bram.name); - log(" Creating %s cell at grid position <%d %d %d>: %s\n", log_id(bram.name), grid_d, grid_a, dupidx, log_id(c)); + SigSpec mktr_wraddr, mktr_wrdata, mktr_wrdata_q; + vector mktr_wren; - for (auto &pi : portinfos) + if (enable_make_transp) { + mktr_wraddr = module->addWire(NEW_ID, bram.abits); + mktr_wrdata = module->addWire(NEW_ID, bram.dbits); + mktr_wrdata_q = module->addWire(NEW_ID, bram.dbits); + module->addDff(NEW_ID, make_transp_clk.first, mktr_wrdata, mktr_wrdata_q, make_transp_clk.second); + for (int grid_a = 0; grid_a*(1 << bram.abits) < mem_size; grid_a++) + mktr_wren.push_back(module->addWire(NEW_ID, make_transp_enbits)); + } + + for (int grid_a = 0; grid_a*(1 << bram.abits) < mem_size; grid_a++) + for (int dupidx = 0; dupidx < dup_count; dupidx++) { - if (pi.dupidx != dupidx) - continue; + Cell *c = module->addCell(module->uniquify(stringf("%s.%d.%d.%d", cell->name.c_str(), grid_d, grid_a, dupidx)), bram.name); + log(" Creating %s cell at grid position <%d %d %d>: %s\n", log_id(bram.name), grid_d, grid_a, dupidx, log_id(c)); - string prefix = stringf("%c%d", pi.group + 'A', pi.index + 1); - const char *pf = prefix.c_str(); + for (auto &vp : variant_params) + c->setParam(vp.first, vp.second); - if (pi.clocks && (!c->hasPort(stringf("\\CLK%d", (pi.clocks-1) % clocks_max + 1)) || pi.sig_clock.wire)) { - c->setPort(stringf("\\CLK%d", (pi.clocks-1) % clocks_max + 1), pi.sig_clock); - if (pi.clkpol > 1 && pi.sig_clock.wire) - c->setParam(stringf("\\CLKPOL%d", (pi.clkpol-1) % clkpol_max + 1), clock_polarities.at(pi.clkpol)); - if (pi.transp > 1 && pi.sig_clock.wire) - c->setParam(stringf("\\TRANSP%d", (pi.transp-1) % transp_max + 1), read_transp.at(pi.transp)); - } - - SigSpec addr_ok; - if (GetSize(pi.sig_addr) > bram.abits) { - SigSpec extra_addr = pi.sig_addr.extract(bram.abits, GetSize(pi.sig_addr) - bram.abits); - SigSpec extra_addr_sel = SigSpec(grid_a, GetSize(extra_addr)); - addr_ok = module->Eq(NEW_ID, extra_addr, extra_addr_sel); - } - - if (pi.enable) + for (auto &pi : portinfos) { - SigSpec sig_en = pi.sig_en; - sig_en.extend_u0((grid_d+1) * pi.enable); - sig_en = sig_en.extract(grid_d * pi.enable, pi.enable); + if (pi.dupidx != dupidx) + continue; - if (!addr_ok.empty()) - sig_en = module->Mux(NEW_ID, SigSpec(0, GetSize(sig_en)), sig_en, addr_ok); + string prefix = stringf("%c%d", pi.group + 'A', pi.index + 1); + const char *pf = prefix.c_str(); - c->setPort(stringf("\\%sEN", pf), sig_en); - } - - SigSpec sig_data = pi.sig_data; - sig_data.extend_u0((grid_d+1) * bram.dbits); - sig_data = sig_data.extract(grid_d * bram.dbits, bram.dbits); - - if (pi.wrmode == 1) { - c->setPort(stringf("\\%sDATA", pf), sig_data); - } else { - SigSpec bram_dout = module->addWire(NEW_ID, bram.dbits); - c->setPort(stringf("\\%sDATA", pf), bram_dout); - - for (int i = bram.dbits-1; i >= 0; i--) - if (sig_data[i].wire == nullptr) { - sig_data.remove(i); - bram_dout.remove(i); - } - - SigSpec addr_ok_q = addr_ok; - if (pi.clocks && !addr_ok.empty()) { - addr_ok_q = module->addWire(NEW_ID); - module->addDff(NEW_ID, pi.sig_clock, addr_ok, addr_ok_q, pi.effective_clkpol); + if (pi.clocks && (!c->hasPort(stringf("\\CLK%d", (pi.clocks-1) % clocks_max + 1)) || pi.sig_clock.wire)) { + c->setPort(stringf("\\CLK%d", (pi.clocks-1) % clocks_max + 1), pi.sig_clock); + if (pi.clkpol > 1 && pi.sig_clock.wire) + c->setParam(stringf("\\CLKPOL%d", (pi.clkpol-1) % clkpol_max + 1), clock_polarities.at(pi.clkpol)); + if (pi.transp > 1 && pi.sig_clock.wire) + c->setParam(stringf("\\TRANSP%d", (pi.transp-1) % transp_max + 1), read_transp.at(pi.transp)); } - dout_cache[sig_data].first.append(addr_ok_q); - dout_cache[sig_data].second.append(bram_dout); - } + SigSpec addr_ok; + if (GetSize(pi.sig_addr) > bram.abits) { + SigSpec extra_addr = pi.sig_addr.extract(bram.abits, GetSize(pi.sig_addr) - bram.abits); + SigSpec extra_addr_sel = SigSpec(grid_a, GetSize(extra_addr)); + addr_ok = module->Eq(NEW_ID, extra_addr, extra_addr_sel); + } - SigSpec sig_addr = pi.sig_addr; - sig_addr.extend_u0(bram.abits); - c->setPort(stringf("\\%sADDR", pf), sig_addr); + if (pi.enable) + { + SigSpec sig_en = pi.sig_en; + sig_en.extend_u0((grid_d+1) * pi.enable); + sig_en = sig_en.extract(grid_d * pi.enable, pi.enable); + + if (!addr_ok.empty()) + sig_en = module->Mux(NEW_ID, SigSpec(0, GetSize(sig_en)), sig_en, addr_ok); + + c->setPort(stringf("\\%sEN", pf), sig_en); + + if (pi.wrmode == 1 && enable_make_transp) + module->connect(mktr_wren[grid_a], sig_en); + } + + SigSpec sig_addr = pi.sig_addr; + sig_addr.extend_u0(bram.abits); + c->setPort(stringf("\\%sADDR", pf), sig_addr); + + if (pi.wrmode == 1 && enable_make_transp && grid_a == 0) + module->connect(mktr_wraddr, sig_addr); + + SigSpec sig_data = pi.sig_data; + sig_data.extend_u0((grid_d+1) * bram.dbits); + sig_data = sig_data.extract(grid_d * bram.dbits, bram.dbits); + + if (pi.wrmode == 1) { + c->setPort(stringf("\\%sDATA", pf), sig_data); + if (enable_make_transp && grid_a == 0) + module->connect(mktr_wrdata, sig_data); + } else { + SigSpec bram_dout = module->addWire(NEW_ID, bram.dbits); + c->setPort(stringf("\\%sDATA", pf), bram_dout); + + if (pi.make_transp) + { + log(" Adding extra logic for transparent port %c%d.%d.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + + SigSpec transp_en_d = module->Mux(NEW_ID, SigSpec(0, make_transp_enbits), + mktr_wren[grid_a], module->Eq(NEW_ID, mktr_wraddr, sig_addr)); + + SigSpec transp_en_q = module->addWire(NEW_ID, make_transp_enbits); + module->addDff(NEW_ID, make_transp_clk.first, transp_en_d, transp_en_q, make_transp_clk.second); + + for (int i = 0; i < make_transp_enbits; i++) { + int en_width = bram.dbits / make_transp_enbits; + SigSpec orig_bram_dout = bram_dout.extract(i * en_width, en_width); + SigSpec bypass_dout = mktr_wrdata_q.extract(i * en_width, en_width); + bram_dout.replace(i * en_width, module->Mux(NEW_ID, orig_bram_dout, bypass_dout, transp_en_q[i])); + } + } + + for (int i = bram.dbits-1; i >= 0; i--) + if (sig_data[i].wire == nullptr) { + sig_data.remove(i); + bram_dout.remove(i); + } + + SigSpec addr_ok_q = addr_ok; + if (pi.clocks && !addr_ok.empty()) { + addr_ok_q = module->addWire(NEW_ID); + module->addDff(NEW_ID, pi.sig_clock, addr_ok, addr_ok_q, pi.effective_clkpol); + } + + dout_cache[sig_data].first.append(addr_ok_q); + dout_cache[sig_data].second.append(bram_dout); + } + } } } @@ -737,127 +919,136 @@ void handle_cell(Cell *cell, const rules_t &rules) log(" %s=%d", it.first.c_str(), it.second); log("\n"); - pool failed_brams; - dict best_rule_cache; + pool> failed_brams; + dict, std::tuple> best_rule_cache; for (int i = 0; i < GetSize(rules.matches); i++) { + auto &match = rules.matches.at(i); + if (!rules.brams.count(rules.matches[i].name)) log_error("No bram description for resource %s found!\n", log_id(rules.matches[i].name)); - auto &match = rules.matches.at(i); - auto &bram = rules.brams.at(match.name); - - if (match.name.in(failed_brams)) - continue; - - int avail_rd_ports = 0; - int avail_wr_ports = 0; - for (int j = 0; j < bram.groups; j++) { - if (GetSize(bram.wrmode) < j || bram.wrmode.at(j) == 0) - avail_rd_ports += GetSize(bram.ports) < j ? bram.ports.at(j) : 0; - if (GetSize(bram.wrmode) < j || bram.wrmode.at(j) != 0) - avail_wr_ports += GetSize(bram.ports) < j ? bram.ports.at(j) : 0; - } - - log(" Checking rule #%d for bram type %s:\n", i, log_id(match.name)); - log(" Bram geometry: abits=%d dbits=%d wports=%d rports=%d\n", bram.abits, bram.dbits, avail_wr_ports, avail_rd_ports); - - int dups = avail_rd_ports ? (match_properties["rports"] + avail_rd_ports - 1) / avail_rd_ports : 1; - match_properties["dups"] = dups; - - log(" Estimated number of duplicates for more read ports: dups=%d\n", match_properties["dups"]); - - int aover = match_properties["words"] % (1 << bram.abits); - int awaste = aover ? (1 << bram.abits) - aover : 0; - match_properties["awaste"] = awaste; - - int dover = match_properties["dbits"] % bram.dbits; - int dwaste = dover ? bram.dbits - dover : 0; - match_properties["dwaste"] = dwaste; - - int bwaste = awaste * bram.dbits + dwaste * (1 << bram.abits) - awaste * dwaste; - match_properties["bwaste"] = bwaste; - - int waste = match_properties["dups"] * bwaste; - match_properties["waste"] = waste; - - int cells = ((match_properties["dbits"] + bram.dbits - 1) / bram.dbits) * ((match_properties["words"] + (1 << bram.abits) - 1) / (1 << bram.abits)); - int efficiency = (100 * match_properties["bits"]) / (dups * cells * bram.dbits * (1 << bram.abits)); - match_properties["efficiency"] = efficiency; - - log(" Metrics for %s: awaste=%d dwaste=%d bwaste=%d waste=%d efficiency=%d\n", - log_id(match.name), awaste, dwaste, bwaste, waste, efficiency); - - for (auto it : match.min_limits) { - if (it.first == "waste" || it.first == "dups") - continue; - if (!match_properties.count(it.first)) - log_error("Unknown property '%s' in match rule for bram type %s.\n", - it.first.c_str(), log_id(match.name)); - if (match_properties[it.first] >= it.second) - continue; - log(" Rule #%d for bram type %s rejected: requirement 'min %s %d' not met.\n", - i, log_id(match.name), it.first.c_str(), it.second); - goto next_match_rule; - } - for (auto it : match.max_limits) { - if (!match_properties.count(it.first)) - log_error("Unknown property '%s' in match rule for bram type %s.\n", - it.first.c_str(), log_id(match.name)); - if (match_properties[it.first] <= it.second) - continue; - log(" Rule #%d for bram type %s rejected: requirement 'max %s %d' not met.\n", - i, log_id(match.name), it.first.c_str(), it.second); - goto next_match_rule; - } - - log(" Rule #%d for bram type %s accepted.\n", i, log_id(match.name)); - - if (match.or_next_if_better || !best_rule_cache.empty()) + for (int vi = 0; vi < GetSize(rules.brams.at(match.name)); vi++) { - if (match.or_next_if_better && i+1 == GetSize(rules.matches)) - log_error("Found 'or_next_if_better' in last match rule.\n"); + auto &bram = rules.brams.at(match.name).at(vi); + bool or_next_if_better = match.or_next_if_better || vi+1 < GetSize(rules.brams.at(match.name)); - if (!replace_cell(cell, bram, match, match_properties, 1)) { - log(" Mapping to bram type %s failed.\n", log_id(match.name)); - failed_brams.insert(match.name); - goto next_match_rule; - } - - log(" Storing for later selection.\n"); - best_rule_cache[i] = match_properties["efficiency"]; - - if (match.or_next_if_better) - goto next_match_rule; - - next_match_rule: - if (match.or_next_if_better || best_rule_cache.empty()) + if (failed_brams.count(pair(bram.name, bram.variant))) continue; - log(" Selecting best of %d rules:\n", GetSize(best_rule_cache)); - int best_rule = best_rule_cache.begin()->first; - - for (auto &it : best_rule_cache) { - if (it.second > best_rule_cache[best_rule]) - best_rule = it.first; - log(" Efficiency for rule %d: %d\n", it.first, it.second); + int avail_rd_ports = 0; + int avail_wr_ports = 0; + for (int j = 0; j < bram.groups; j++) { + if (GetSize(bram.wrmode) < j || bram.wrmode.at(j) == 0) + avail_rd_ports += GetSize(bram.ports) < j ? bram.ports.at(j) : 0; + if (GetSize(bram.wrmode) < j || bram.wrmode.at(j) != 0) + avail_wr_ports += GetSize(bram.ports) < j ? bram.ports.at(j) : 0; } - log(" Selected rule %d with efficiency %d.\n", best_rule, best_rule_cache[best_rule]); - best_rule_cache.clear(); + log(" Checking rule #%d for bram type %s (variant %d):\n", i+1, log_id(bram.name), bram.variant); + log(" Bram geometry: abits=%d dbits=%d wports=%d rports=%d\n", bram.abits, bram.dbits, avail_wr_ports, avail_rd_ports); - if (!replace_cell(cell, rules.brams.at(rules.matches.at(best_rule).name), rules.matches.at(best_rule), match_properties, 2)) - log_error("Mapping to bram type %s after pre-selection failed.\n", log_id(rules.matches.at(best_rule).name)); + int dups = avail_rd_ports ? (match_properties["rports"] + avail_rd_ports - 1) / avail_rd_ports : 1; + match_properties["dups"] = dups; + + log(" Estimated number of duplicates for more read ports: dups=%d\n", match_properties["dups"]); + + int aover = match_properties["words"] % (1 << bram.abits); + int awaste = aover ? (1 << bram.abits) - aover : 0; + match_properties["awaste"] = awaste; + + int dover = match_properties["dbits"] % bram.dbits; + int dwaste = dover ? bram.dbits - dover : 0; + match_properties["dwaste"] = dwaste; + + int bwaste = awaste * bram.dbits + dwaste * (1 << bram.abits) - awaste * dwaste; + match_properties["bwaste"] = bwaste; + + int waste = match_properties["dups"] * bwaste; + match_properties["waste"] = waste; + + int cells = ((match_properties["dbits"] + bram.dbits - 1) / bram.dbits) * ((match_properties["words"] + (1 << bram.abits) - 1) / (1 << bram.abits)); + int efficiency = (100 * match_properties["bits"]) / (dups * cells * bram.dbits * (1 << bram.abits)); + match_properties["efficiency"] = efficiency; + + log(" Metrics for %s: awaste=%d dwaste=%d bwaste=%d waste=%d efficiency=%d\n", + log_id(match.name), awaste, dwaste, bwaste, waste, efficiency); + + for (auto it : match.min_limits) { + if (it.first == "waste" || it.first == "dups" || it.first == "acells" || it.first == "dcells" || it.first == "cells") + continue; + if (!match_properties.count(it.first)) + log_error("Unknown property '%s' in match rule for bram type %s.\n", + it.first.c_str(), log_id(match.name)); + if (match_properties[it.first] >= it.second) + continue; + log(" Rule #%d for bram type %s (variant %d) rejected: requirement 'min %s %d' not met.\n", + i+1, log_id(bram.name), bram.variant, it.first.c_str(), it.second); + goto next_match_rule; + } + for (auto it : match.max_limits) { + if (it.first == "acells" || it.first == "dcells" || it.first == "cells") + continue; + if (!match_properties.count(it.first)) + log_error("Unknown property '%s' in match rule for bram type %s.\n", + it.first.c_str(), log_id(match.name)); + if (match_properties[it.first] <= it.second) + continue; + log(" Rule #%d for bram type %s (variant %d) rejected: requirement 'max %s %d' not met.\n", + i+1, log_id(bram.name), bram.variant, it.first.c_str(), it.second); + goto next_match_rule; + } + + log(" Rule #%d for bram type %s (variant %d) accepted.\n", i+1, log_id(bram.name), bram.variant); + + if (or_next_if_better || !best_rule_cache.empty()) + { + if (or_next_if_better && i+1 == GetSize(rules.matches) && vi+1 == GetSize(rules.brams.at(match.name))) + log_error("Found 'or_next_if_better' in last match rule.\n"); + + if (!replace_cell(cell, rules, bram, match, match_properties, 1)) { + log(" Mapping to bram type %s failed.\n", log_id(match.name)); + failed_brams.insert(pair(bram.name, bram.variant)); + goto next_match_rule; + } + + log(" Storing for later selection.\n"); + best_rule_cache[pair(i, vi)] = std::tuple(match_properties["efficiency"], -match_properties["cells"], -match_properties["acells"]); + + if (or_next_if_better) + goto next_match_rule; + + next_match_rule: + if (or_next_if_better || best_rule_cache.empty()) + continue; + + log(" Selecting best of %d rules:\n", GetSize(best_rule_cache)); + pair best_rule = best_rule_cache.begin()->first; + + for (auto &it : best_rule_cache) { + if (it.second > best_rule_cache[best_rule]) + best_rule = it.first; + log(" Efficiency for rule %d.%d: efficiency=%d, cells=%d, acells=%d\n", it.first.first+1, it.first.second+1, + std::get<0>(it.second), -std::get<1>(it.second), -std::get<2>(it.second)); + } + + log(" Selected rule %d.%d with efficiency %d.\n", best_rule.first+1, best_rule.second+1, std::get<0>(best_rule_cache[best_rule])); + best_rule_cache.clear(); + + auto &best_bram = rules.brams.at(rules.matches.at(best_rule.first).name).at(best_rule.second); + if (!replace_cell(cell, rules, best_bram, rules.matches.at(best_rule.first), match_properties, 2)) + log_error("Mapping to bram type %s (variant %d) after pre-selection failed.\n", log_id(best_bram.name), best_bram.variant); + return; + } + + if (!replace_cell(cell, rules, bram, match, match_properties, 0)) { + log(" Mapping to bram type %s failed.\n", log_id(match.name)); + failed_brams.insert(pair(bram.name, bram.variant)); + goto next_match_rule; + } return; } - - if (!replace_cell(cell, bram, match, match_properties, 0)) { - log(" Mapping to bram type %s failed.\n", log_id(match.name)); - failed_brams.insert(match.name); - goto next_match_rule; - } - return; } log(" No acceptable bram resources found.\n"); @@ -903,6 +1094,12 @@ struct MemoryBramPass : public Pass { log("and a value greater than 1 means configurable. All groups with the same value\n"); log("greater than 1 share the same configuration bit.\n"); log("\n"); + log("Using the same bram name in different bram blocks will create different variants\n"); + log("of the bram. Verilog configration parameters for the bram are created as needed.\n"); + log("\n"); + log("It is also possible to create variants by repeating statements in the bram block\n"); + log("and appending '@

yosys.js example application

+
+

yosys>
+ + + + diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index d8a433164..6b6846e20 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -24,9 +24,11 @@ passes/techmap/techmap.inc: techlibs/common/techmap.v passes/techmap/techmap.o: passes/techmap/techmap.inc +ifneq ($(CONFIG),emcc) TARGETS += yosys-filterlib$(EXE) EXTRA_OBJS += passes/techmap/filterlib.o yosys-filterlib$(EXE): passes/techmap/filterlib.o $(P) $(CXX) -o yosys-filterlib$(EXE) $(LDFLAGS) $^ $(LDLIBS) +endif From a54c994e2be340d3d036c160e5cd065a72fe5603 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 15 Feb 2015 12:57:41 +0100 Subject: [PATCH 428/492] Cosmetic fixes in "hierarchy" for blackbox modules --- passes/hierarchy/hierarchy.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 58b796a62..8f2422bd0 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -268,7 +268,7 @@ void hierarchy_worker(RTLIL::Design *design, std::set &used, RTL if (indent == 0) log("Top module: %s\n", mod->name.c_str()); - else + else if (!mod->get_bool_attribute("\\blackbox")) log("Used module: %*s%s\n", indent, "", mod->name.c_str()); used.insert(mod); @@ -295,6 +295,7 @@ void hierarchy(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib, bool f if (used.count(it.second) == 0) del_modules.push_back(it.second); + int del_counter = 0; for (auto mod : del_modules) { if (first_pass && mod->name.substr(0, 9) == "$abstract") continue; @@ -302,10 +303,11 @@ void hierarchy(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib, bool f continue; log("Removing unused module `%s'.\n", mod->name.c_str()); design->modules_.erase(mod->name); + del_counter++; delete mod; } - log("Removed %d unused modules.\n", GetSize(del_modules)); + log("Removed %d unused modules.\n", del_counter); } bool set_keep_assert(std::map &cache, RTLIL::Module *mod) From 40f021e1367af8cc8cd2ea133ba4cb0d2f342cbd Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 15 Feb 2015 12:58:12 +0100 Subject: [PATCH 429/492] Added "check -noinit" --- passes/cmds/check.cc | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc index 6840572eb..824131a7a 100644 --- a/passes/cmds/check.cc +++ b/passes/cmds/check.cc @@ -31,7 +31,7 @@ struct CheckPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" check [selection]\n"); + log(" check [options] [selection]\n"); log("\n"); log("This pass identifies the following problems in the current design:\n"); log("\n"); @@ -41,15 +41,27 @@ struct CheckPass : public Pass { log("\n"); log(" - used wires that do not have a driver\n"); log("\n"); + log("When called with -noinit then this command also checks for wires which have\n"); + log("the 'init' attribute set.\n"); + log("\n"); } virtual void execute(std::vector args, RTLIL::Design *design) { int counter = 0; + bool noinit = false; + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-noinit") { + noinit = true; + continue; + } + break; + } + extra_args(args, argidx, design); log_header("Executing CHECK pass (checking for obvious problems).\n"); - extra_args(args, 1, design); - for (auto module : design->selected_whole_modules_warn()) { if (module->has_processes_warn()) @@ -93,6 +105,10 @@ struct CheckPass : public Pass { if (wire->port_output) for (auto bit : sigmap(wire)) if (bit.wire) used_wires.insert(bit); + if (noinit && wire->attributes.count("\\init")) { + log_warning("Wire %s.%s has an unprocessed 'init' attribute.\n", log_id(module), log_id(wire)); + counter++; + } } for (auto it : wire_drivers) From 881dcd8af988664b92a85daa5d82e90b1df29b51 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 15 Feb 2015 13:00:00 +0100 Subject: [PATCH 430/492] Added final checks to "synth" and "synth_xilinx" --- techlibs/common/synth.cc | 21 ++++++++++++++------- techlibs/xilinx/synth_xilinx.cc | 10 ++++++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index a50db53ee..56ab6eaff 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -90,12 +90,14 @@ struct SynthPass : public Pass { log(" techmap\n"); log(" opt -fast\n"); #ifdef YOSYS_ENABLE_ABC - log("\n"); - log(" abc:\n"); log(" abc -fast\n"); log(" opt -fast\n"); #endif log("\n"); + log(" check:\n"); + log(" hierarchy -check\n"); + log(" check\n"); + log("\n"); } virtual void execute(std::vector args, RTLIL::Design *design) { @@ -172,15 +174,20 @@ struct SynthPass : public Pass { Pass::call(design, "opt -full"); Pass::call(design, "techmap"); Pass::call(design, "opt -fast"); + + if (!noabc) { + #ifdef YOSYS_ENABLE_ABC + Pass::call(design, "abc -fast"); + Pass::call(design, "opt -fast"); + #endif + } } - #ifdef YOSYS_ENABLE_ABC - if (check_label(active, run_from, run_to, "abc") && !noabc) + if (check_label(active, run_from, run_to, "check")) { - Pass::call(design, "abc -fast"); - Pass::call(design, "opt -fast"); + Pass::call(design, "hierarchy -check"); + Pass::call(design, "check"); } - #endif log_pop(); } diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 7812fa290..02207593a 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -98,6 +98,10 @@ struct SynthXilinxPass : public Pass { log(" techmap -map +/xilinx/cells_map.v\n"); log(" clean\n"); log("\n"); + log(" check:\n"); + log(" hierarchy -check\n"); + log(" check -noinit\n"); + log("\n"); log(" edif:\n"); log(" write_edif synth.edif\n"); log("\n"); @@ -195,6 +199,12 @@ struct SynthXilinxPass : public Pass { Pass::call(design, "clean"); } + if (check_label(active, run_from, run_to, "check")) + { + Pass::call(design, "hierarchy -check"); + Pass::call(design, "check -noinit"); + } + if (check_label(active, run_from, run_to, "edif")) { if (!edif_file.empty()) From 4d34d031f9c0b62cc4f669114c60ecdfdc555274 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 15 Feb 2015 13:25:15 +0100 Subject: [PATCH 431/492] Added "stat" to "synth" and "synth_xilinx" --- techlibs/common/synth.cc | 2 ++ techlibs/xilinx/synth_xilinx.cc | 2 ++ 2 files changed, 4 insertions(+) diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 56ab6eaff..c3e7288db 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -96,6 +96,7 @@ struct SynthPass : public Pass { log("\n"); log(" check:\n"); log(" hierarchy -check\n"); + log(" stat\n"); log(" check\n"); log("\n"); } @@ -186,6 +187,7 @@ struct SynthPass : public Pass { if (check_label(active, run_from, run_to, "check")) { Pass::call(design, "hierarchy -check"); + Pass::call(design, "stat"); Pass::call(design, "check"); } diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 02207593a..836ba9add 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -100,6 +100,7 @@ struct SynthXilinxPass : public Pass { log("\n"); log(" check:\n"); log(" hierarchy -check\n"); + log(" stat\n"); log(" check -noinit\n"); log("\n"); log(" edif:\n"); @@ -202,6 +203,7 @@ struct SynthXilinxPass : public Pass { if (check_label(active, run_from, run_to, "check")) { Pass::call(design, "hierarchy -check"); + Pass::call(design, "stat"); Pass::call(design, "check -noinit"); } From c2cc342e1a3d223caf1059fd2f255b0985ded61c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 15 Feb 2015 16:16:08 +0100 Subject: [PATCH 432/492] Improved yosys.js example --- misc/yosys.html | 132 ++++++++++++++++++++++++++---------------------- 1 file changed, 72 insertions(+), 60 deletions(-) diff --git a/misc/yosys.html b/misc/yosys.html index c82bc1871..929d0dd3b 100644 --- a/misc/yosys.html +++ b/misc/yosys.html @@ -1,60 +1,72 @@ - - - yosys.js example application - - -

yosys.js example application

-
-

yosys>
- - - - + + yosys.js example application + +

yosys.js example application

+
+

Loading...
+ + + + From 8d45f81046a159df38e20b00cf0d74b1bb02a073 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 15 Feb 2015 17:14:09 +0100 Subject: [PATCH 433/492] More emcc stuff --- Makefile | 5 ++++- kernel/yosys.cc | 13 ++++++++++--- misc/yosys.html | 38 +++++++++++++++++++++++++------------- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 775fce1ad..c762bd38c 100644 --- a/Makefile +++ b/Makefile @@ -95,10 +95,11 @@ CXXFLAGS += -std=gnu++0x -Os else ifeq ($(CONFIG),emcc) CXX = emcc -CXXFLAGS := -std=c++11 $(filter-out -fPIC,$(filter-out -ggdb,$(CXXFLAGS))) +CXXFLAGS := -std=c++11 $(filter-out -fPIC -ggdb,$(CXXFLAGS)) EMCCFLAGS := -Os -Wno-warn-absolute-paths EMCCFLAGS += --memory-init-file 0 -s NO_EXIT_RUNTIME=1 EMCCFLAGS += -s EXPORTED_FUNCTIONS="['_main','_run','_prompt']" +EMCCFLAGS += --embed-file share # https://github.com/kripken/emscripten/blob/master/src/settings.js # EMCCFLAGS += -s ALLOW_MEMORY_GROWTH=1 # EMCCFLAGS += -s DISABLE_EXCEPTION_CATCHING=0 @@ -111,7 +112,9 @@ LDFLAGS += $(EMCCFLAGS) LDLIBS = EXE = .js +TARGETS := $(filter-out yosys-config,$(TARGETS)) EXTRA_TARGETS += yosys.html + yosys.html: misc/yosys.html $(P) cp misc/yosys.html yosys.html diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 530d78796..b54836621 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -619,26 +619,33 @@ std::string proc_self_dirname() #error Dont know how to determine process executable base path! #endif +#ifdef EMSCRIPTEN +std::string proc_share_dirname() +{ + return "/share"; +} +#else std::string proc_share_dirname() { std::string proc_self_path = proc_self_dirname(); -#ifdef _WIN32 +# ifdef _WIN32 std::string proc_share_path = proc_self_path + "share\\"; if (check_file_exists(proc_share_path, true)) return proc_share_path; proc_share_path = proc_self_path + "..\\share\\"; if (check_file_exists(proc_share_path, true)) return proc_share_path; -#else +# else std::string proc_share_path = proc_self_path + "share/"; if (check_file_exists(proc_share_path, true)) return proc_share_path; proc_share_path = proc_self_path + "../share/yosys/"; if (check_file_exists(proc_share_path, true)) return proc_share_path; -#endif +# endif log_error("proc_share_dirname: unable to determine share/ directory!\n"); } +#endif bool fgetline(FILE *f, std::string &buffer) { diff --git a/misc/yosys.html b/misc/yosys.html index 929d0dd3b..29d89e6fe 100644 --- a/misc/yosys.html +++ b/misc/yosys.html @@ -4,18 +4,18 @@

yosys.js example application


Loading...
- + +

Loading...