aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile9
-rw-r--r--README.md2
-rw-r--r--backends/json/json.cc4
-rw-r--r--backends/protobuf/.gitignore2
-rw-r--r--backends/protobuf/Makefile.inc8
-rw-r--r--backends/protobuf/protobuf.cc370
-rw-r--r--backends/smt2/Makefile.inc2
-rw-r--r--frontends/ast/ast.cc13
-rw-r--r--frontends/ast/genrtlil.cc180
-rw-r--r--frontends/ast/simplify.cc228
-rw-r--r--frontends/blif/blifparse.cc40
-rw-r--r--frontends/liberty/liberty.cc2
-rw-r--r--frontends/verific/verific.cc271
-rw-r--r--frontends/verific/verific.h3
-rw-r--r--frontends/verific/verificsva.cc111
-rw-r--r--frontends/verilog/const2ast.cc8
-rw-r--r--frontends/verilog/verilog_frontend.cc8
-rw-r--r--kernel/log.cc84
-rw-r--r--kernel/log.h5
-rw-r--r--kernel/yosys.cc2
-rw-r--r--misc/yosys.proto175
-rw-r--r--passes/cmds/stat.cc8
-rw-r--r--passes/hierarchy/hierarchy.cc20
-rw-r--r--passes/sat/Makefile.inc1
-rw-r--r--passes/sat/async2sync.cc147
-rw-r--r--passes/techmap/Makefile.inc2
-rw-r--r--passes/techmap/deminout.cc32
-rw-r--r--passes/techmap/dff2dffe.cc14
-rw-r--r--passes/techmap/dff2dffs.cc142
-rw-r--r--passes/techmap/extract_reduce.cc1
-rw-r--r--techlibs/ecp5/Makefile.inc8
-rw-r--r--techlibs/ecp5/arith_map.v79
-rw-r--r--techlibs/ecp5/cells_map.v135
-rw-r--r--techlibs/ecp5/cells_sim.v448
-rw-r--r--techlibs/ecp5/dram.txt16
-rw-r--r--techlibs/ecp5/drams_map.v28
-rw-r--r--techlibs/ecp5/synth_ecp5.cc331
-rw-r--r--techlibs/ice40/cells_sim.v8
-rw-r--r--techlibs/ice40/ice40_opt.cc34
-rw-r--r--techlibs/ice40/synth_ice40.cc31
40 files changed, 2688 insertions, 324 deletions
diff --git a/Makefile b/Makefile
index 2db6612a7..be266b628 100644
--- a/Makefile
+++ b/Makefile
@@ -15,6 +15,7 @@ ENABLE_EDITLINE := 0
ENABLE_VERIFIC := 0
ENABLE_COVER := 1
ENABLE_LIBYOSYS := 0
+ENABLE_PROTOBUF := 0
# other configuration flags
ENABLE_GPROF := 0
@@ -106,7 +107,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 = 6df1396
+ABCREV = ae6716b
ABCPULL = 1
ABCURL ?= https://github.com/berkeley-abc/abc
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1
@@ -275,7 +276,7 @@ endif
ifeq ($(CONFIG),mxe)
CXXFLAGS += -DYOSYS_ENABLE_TCL
-LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32
+LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz
else
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL
ifeq ($(OS), FreeBSD)
@@ -325,6 +326,10 @@ CXXFLAGS += $(patsubst %,-I$(VERIFIC_DIR)/%,$(VERIFIC_COMPONENTS)) -DYOSYS_ENABL
LDLIBS += $(patsubst %,$(VERIFIC_DIR)/%/*-linux.a,$(VERIFIC_COMPONENTS)) -lz
endif
+ifeq ($(ENABLE_PROTOBUF),1)
+LDLIBS += $(shell pkg-config --cflags --libs protobuf)
+endif
+
ifeq ($(ENABLE_COVER),1)
CXXFLAGS += -DYOSYS_ENABLE_COVER
endif
diff --git a/README.md b/README.md
index c02691d94..424d9bbf2 100644
--- a/README.md
+++ b/README.md
@@ -389,7 +389,7 @@ Verilog Attributes and non-standard features
Non-standard or SystemVerilog features for formal verification
==============================================================
-- Support for ``assert``, ``assume``, ``restrict``, and ``cover'' is enabled
+- Support for ``assert``, ``assume``, ``restrict``, and ``cover`` is enabled
when ``read_verilog`` is called with ``-formal``.
- The system task ``$initstate`` evaluates to 1 in the initial state and
diff --git a/backends/json/json.cc b/backends/json/json.cc
index d3b7077a2..1a3ca64a3 100644
--- a/backends/json/json.cc
+++ b/backends/json/json.cc
@@ -93,8 +93,10 @@ struct JsonWriter
f << get_string(param.second.decode_string());
else if (GetSize(param.second.bits) > 32)
f << get_string(param.second.as_string());
- else
+ else if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0)
f << stringf("%d", param.second.as_int());
+ else
+ f << stringf("%u", param.second.as_int());
first = false;
}
}
diff --git a/backends/protobuf/.gitignore b/backends/protobuf/.gitignore
new file mode 100644
index 000000000..849b38d45
--- /dev/null
+++ b/backends/protobuf/.gitignore
@@ -0,0 +1,2 @@
+yosys.pb.cc
+yosys.pb.h
diff --git a/backends/protobuf/Makefile.inc b/backends/protobuf/Makefile.inc
new file mode 100644
index 000000000..834cad42c
--- /dev/null
+++ b/backends/protobuf/Makefile.inc
@@ -0,0 +1,8 @@
+ifeq ($(ENABLE_PROTOBUF),1)
+
+backends/protobuf/yosys.pb.cc backends/protobuf/yosys.pb.h: misc/yosys.proto
+ $(Q) cd misc && protoc --cpp_out "../backends/protobuf" yosys.proto
+
+OBJS += backends/protobuf/protobuf.o backends/protobuf/yosys.pb.o
+
+endif
diff --git a/backends/protobuf/protobuf.cc b/backends/protobuf/protobuf.cc
new file mode 100644
index 000000000..9a6fedee7
--- /dev/null
+++ b/backends/protobuf/protobuf.cc
@@ -0,0 +1,370 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
+ *
+ * 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 <google/protobuf/text_format.h>
+
+#include "kernel/rtlil.h"
+#include "kernel/register.h"
+#include "kernel/sigtools.h"
+#include "kernel/celltypes.h"
+#include "kernel/cellaigs.h"
+#include "kernel/log.h"
+#include "yosys.pb.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct ProtobufDesignSerializer
+{
+ bool aig_mode_;
+ bool use_selection_;
+ yosys::pb::Design *pb_;
+
+ Design *design_;
+ Module *module_;
+
+ SigMap sigmap_;
+ int sigidcounter_;
+ dict<SigBit, uint64_t> sigids_;
+ pool<Aig> aig_models_;
+
+
+ ProtobufDesignSerializer(bool use_selection, bool aig_mode) :
+ aig_mode_(aig_mode), use_selection_(use_selection) { }
+
+ string get_name(IdString name)
+ {
+ return RTLIL::unescape_id(name);
+ }
+
+
+ void serialize_parameters(google::protobuf::Map<std::string, yosys::pb::Parameter> *out,
+ const dict<IdString, Const> &parameters)
+ {
+ for (auto &param : parameters) {
+ std::string key = get_name(param.first);
+
+
+ yosys::pb::Parameter pb_param;
+
+ if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) {
+ pb_param.set_str(param.second.decode_string());
+ } else if (GetSize(param.second.bits) > 64) {
+ pb_param.set_str(param.second.as_string());
+ } else {
+ pb_param.set_int_(param.second.as_int());
+ }
+
+ (*out)[key] = pb_param;
+ }
+ }
+
+ void get_bits(yosys::pb::BitVector *out, SigSpec sig)
+ {
+ for (auto bit : sigmap_(sig)) {
+ auto sig = out->add_signal();
+
+ // Constant driver.
+ if (bit.wire == nullptr) {
+ if (bit == State::S0) sig->set_constant(sig->CONSTANT_DRIVER_LOW);
+ else if (bit == State::S1) sig->set_constant(sig->CONSTANT_DRIVER_HIGH);
+ else if (bit == State::Sz) sig->set_constant(sig->CONSTANT_DRIVER_Z);
+ else sig->set_constant(sig->CONSTANT_DRIVER_X);
+ continue;
+ }
+
+ // Signal - give it a unique identifier.
+ if (sigids_.count(bit) == 0) {
+ sigids_[bit] = sigidcounter_++;
+ }
+ sig->set_id(sigids_[bit]);
+ }
+ }
+
+ void serialize_module(yosys::pb::Module* out, Module *module)
+ {
+ module_ = module;
+ log_assert(module_->design == design_);
+ sigmap_.set(module_);
+ sigids_.clear();
+ sigidcounter_ = 0;
+
+ serialize_parameters(out->mutable_attribute(), module_->attributes);
+
+ for (auto n : module_->ports) {
+ Wire *w = module->wire(n);
+ if (use_selection_ && !module_->selected(w))
+ continue;
+
+ yosys::pb::Module::Port pb_port;
+ pb_port.set_direction(w->port_input ? w->port_output ?
+ yosys::pb::DIRECTION_INOUT : yosys::pb::DIRECTION_INPUT : yosys::pb::DIRECTION_OUTPUT);
+ get_bits(pb_port.mutable_bits(), w);
+ (*out->mutable_port())[get_name(n)] = pb_port;
+ }
+
+ for (auto c : module_->cells()) {
+ if (use_selection_ && !module_->selected(c))
+ continue;
+
+ yosys::pb::Module::Cell pb_cell;
+ pb_cell.set_hide_name(c->name[0] == '$');
+ pb_cell.set_type(get_name(c->type));
+
+ if (aig_mode_) {
+ Aig aig(c);
+ if (aig.name.empty())
+ continue;
+ pb_cell.set_model(aig.name);
+ aig_models_.insert(aig);
+ }
+ serialize_parameters(pb_cell.mutable_parameter(), c->parameters);
+ serialize_parameters(pb_cell.mutable_attribute(), c->attributes);
+
+ if (c->known()) {
+ for (auto &conn : c->connections()) {
+ yosys::pb::Direction direction = yosys::pb::DIRECTION_OUTPUT;
+ if (c->input(conn.first))
+ direction = c->output(conn.first) ? yosys::pb::DIRECTION_INOUT : yosys::pb::DIRECTION_INPUT;
+ (*pb_cell.mutable_port_direction())[get_name(conn.first)] = direction;
+ }
+ }
+ for (auto &conn : c->connections()) {
+ yosys::pb::BitVector vec;
+ get_bits(&vec, conn.second);
+ (*pb_cell.mutable_connection())[get_name(conn.first)] = vec;
+ }
+
+ (*out->mutable_cell())[get_name(c->name)] = pb_cell;
+ }
+
+ for (auto w : module_->wires()) {
+ if (use_selection_ && !module_->selected(w))
+ continue;
+
+ auto netname = out->add_netname();
+ netname->set_hide_name(w->name[0] == '$');
+ get_bits(netname->mutable_bits(), w);
+ serialize_parameters(netname->mutable_attributes(), w->attributes);
+ }
+ }
+
+
+ void serialize_models(google::protobuf::Map<string, yosys::pb::Model> *models)
+ {
+ for (auto &aig : aig_models_) {
+ yosys::pb::Model pb_model;
+ for (auto &node : aig.nodes) {
+ auto pb_node = pb_model.add_node();
+ if (node.portbit >= 0) {
+ if (node.inverter) {
+ pb_node->set_type(pb_node->TYPE_NPORT);
+ } else {
+ pb_node->set_type(pb_node->TYPE_PORT);
+ }
+ auto port = pb_node->mutable_port();
+ port->set_portname(log_id(node.portname));
+ port->set_bitindex(node.portbit);
+ } else if (node.left_parent < 0 && node.right_parent < 0) {
+ if (node.inverter) {
+ pb_node->set_type(pb_node->TYPE_TRUE);
+ } else {
+ pb_node->set_type(pb_node->TYPE_FALSE);
+ }
+ } else {
+ if (node.inverter) {
+ pb_node->set_type(pb_node->TYPE_NAND);
+ } else {
+ pb_node->set_type(pb_node->TYPE_AND);
+ }
+ auto gate = pb_node->mutable_gate();
+ gate->set_left(node.left_parent);
+ gate->set_right(node.right_parent);
+ }
+ for (auto &op : node.outports) {
+ auto pb_op = pb_node->add_out_port();
+ pb_op->set_name(log_id(op.first));
+ pb_op->set_bit_index(op.second);
+ }
+ }
+ (*models)[aig.name] = pb_model;
+ }
+ }
+
+ void serialize_design(yosys::pb::Design *pb, Design *design)
+ {
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+ pb_ = pb;
+ pb_->Clear();
+ pb_->set_creator(yosys_version_str);
+
+ design_ = design;
+ design_->sort();
+
+ auto modules = use_selection_ ? design_->selected_modules() : design_->modules();
+ for (auto mod : modules) {
+ yosys::pb::Module pb_mod;
+ serialize_module(&pb_mod, mod);
+ (*pb->mutable_modules())[mod->name.str()] = pb_mod;
+ }
+
+ serialize_models(pb_->mutable_models());
+ }
+};
+
+struct ProtobufBackend : public Backend {
+ ProtobufBackend(): Backend("protobuf", "write design to a Protocol Buffer file") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" write_protobuf [options] [filename]\n");
+ log("\n");
+ log("Write a JSON netlist of the current design.\n");
+ log("\n");
+ log(" -aig\n");
+ log(" include AIG models for the different gate types\n");
+ log("\n");
+ log(" -text\n");
+ log(" output protobuf in Text/ASCII representation\n");
+ log("\n");
+ log("The schema of the output Protocol Buffer is defined in misc/yosys.pb in the\n");
+ log("Yosys source code distribution.\n");
+ log("\n");
+ }
+ virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ {
+ bool aig_mode = false;
+ bool text_mode = false;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-aig") {
+ aig_mode = true;
+ continue;
+ }
+ if (args[argidx] == "-text") {
+ text_mode = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(f, filename, args, argidx);
+
+ log_header(design, "Executing Protobuf backend.\n");
+
+ yosys::pb::Design pb;
+ ProtobufDesignSerializer serializer(false, aig_mode);
+ serializer.serialize_design(&pb, design);
+
+ if (text_mode) {
+ string out;
+ google::protobuf::TextFormat::PrintToString(pb, &out);
+ *f << out;
+ } else {
+ pb.SerializeToOstream(f);
+ }
+ }
+} ProtobufBackend;
+
+struct ProtobufPass : public Pass {
+ ProtobufPass() : Pass("protobuf", "write design in Protobuf format") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" protobuf [options] [selection]\n");
+ log("\n");
+ log("Write a JSON netlist of all selected objects.\n");
+ log("\n");
+ log(" -o <filename>\n");
+ log(" write to the specified file.\n");
+ log("\n");
+ log(" -aig\n");
+ log(" include AIG models for the different gate types\n");
+ log("\n");
+ log(" -text\n");
+ log(" output protobuf in Text/ASCII representation\n");
+ log("\n");
+ log("The schema of the output Protocol Buffer is defined in misc/yosys.pb in the\n");
+ log("Yosys source code distribution.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ std::string filename;
+ bool aig_mode = false;
+ bool text_mode = false;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-o" && argidx+1 < args.size()) {
+ filename = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-aig") {
+ aig_mode = true;
+ continue;
+ }
+ if (args[argidx] == "-text") {
+ text_mode = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ std::ostream *f;
+ std::stringstream buf;
+
+ if (!filename.empty()) {
+ std::ofstream *ff = new std::ofstream;
+ ff->open(filename.c_str(), std::ofstream::trunc);
+ if (ff->fail()) {
+ delete ff;
+ log_error("Can't open file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
+ }
+ f = ff;
+ } else {
+ f = &buf;
+ }
+
+ yosys::pb::Design pb;
+ ProtobufDesignSerializer serializer(true, aig_mode);
+ serializer.serialize_design(&pb, design);
+
+ if (text_mode) {
+ string out;
+ google::protobuf::TextFormat::PrintToString(pb, &out);
+ *f << out;
+ } else {
+ pb.SerializeToOstream(f);
+ }
+
+ if (!filename.empty()) {
+ delete f;
+ } else {
+ log("%s", buf.str().c_str());
+ }
+ }
+} ProtobufPass;
+
+PRIVATE_NAMESPACE_END;
diff --git a/backends/smt2/Makefile.inc b/backends/smt2/Makefile.inc
index eacda2734..dce82f01a 100644
--- a/backends/smt2/Makefile.inc
+++ b/backends/smt2/Makefile.inc
@@ -6,7 +6,7 @@ ifneq ($(CONFIG),emcc)
TARGETS += yosys-smtbmc
yosys-smtbmc: backends/smt2/smtbmc.py
- $(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(__file__) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' < $< > $@.new
+ $(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' < $< > $@.new
$(Q) chmod +x $@.new
$(Q) mv $@.new $@
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 999202b47..54ce6a05d 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -171,8 +171,8 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id)
AstNode *attr = attributes.at(id);
if (attr->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- id.c_str(), attr->filename.c_str(), attr->linenum);
+ log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n",
+ id.c_str());
return attr->integer != 0;
}
@@ -955,8 +955,8 @@ static AstModule* process_module(AstNode *ast, bool defer)
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), ast->filename.c_str(), ast->linenum);
+ log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
current_module->attributes[attr.first] = attr.second->asAttrConst();
}
for (size_t i = 0; i < ast->children.size(); i++) {
@@ -1044,8 +1044,8 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
if (design->has((*it)->str)) {
RTLIL::Module *existing_mod = design->module((*it)->str);
if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
- log_error("Re-definition of module `%s' at %s:%d!\n",
- (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
+ log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n",
+ (*it)->str.c_str());
} else if (nooverwrite) {
log("Ignoring re-definition of module `%s' at %s:%d.\n",
(*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
@@ -1197,4 +1197,3 @@ void AST::use_internal_line_num()
}
YOSYS_NAMESPACE_END
-
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 40cbbc2a3..0f7e910f3 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -55,8 +55,8 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_wi
if (gen_attributes)
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), that->filename.c_str(), that->linenum);
+ log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -89,8 +89,8 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
if (that != NULL)
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), that->filename.c_str(), that->linenum);
+ log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -117,8 +117,8 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_wi
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), that->filename.c_str(), that->linenum);
+ log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -152,8 +152,8 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), that->filename.c_str(), that->linenum);
+ log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -207,8 +207,8 @@ struct AST_INTERNAL::ProcessGenerator
proc->name = stringf("$proc$%s:%d$%d", always->filename.c_str(), always->linenum, autoidx++);
for (auto &attr : always->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), always->filename.c_str(), always->linenum);
+ log_file_error(always->filename, always->linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
proc->attributes[attr.first] = attr.second->asAttrConst();
}
current_module->processes[proc->name] = proc;
@@ -238,7 +238,7 @@ struct AST_INTERNAL::ProcessGenerator
if (found_anyedge_syncs) {
if (found_global_syncs)
- log_error("Found non-synthesizable event list at %s:%d!\n", always->filename.c_str(), always->linenum);
+ log_file_error(always->filename, always->linenum, "Found non-synthesizable event list!\n");
log("Note: Assuming pure combinatorial block at %s:%d in\n", always->filename.c_str(), always->linenum);
log("compliance with IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002. Recommending\n");
log("use of @* instead of @(...) for better match of synthesis and simulation.\n");
@@ -253,12 +253,12 @@ struct AST_INTERNAL::ProcessGenerator
continue;
found_clocked_sync = true;
if (found_global_syncs || found_anyedge_syncs)
- log_error("Found non-synthesizable event list at %s:%d!\n", always->filename.c_str(), always->linenum);
+ log_file_error(always->filename, always->linenum, "Found non-synthesizable event list!\n");
RTLIL::SyncRule *syncrule = new RTLIL::SyncRule;
syncrule->type = child->type == AST_POSEDGE ? RTLIL::STp : RTLIL::STn;
syncrule->signal = child->children[0]->genRTLIL();
if (GetSize(syncrule->signal) != 1)
- log_error("Found posedge/negedge event on a signal that is not 1 bit wide at %s:%d!\n", always->filename.c_str(), always->linenum);
+ log_file_error(always->filename, always->linenum, "Found posedge/negedge event on a signal that is not 1 bit wide!\n");
addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, true);
proc->syncs.push_back(syncrule);
}
@@ -480,8 +480,8 @@ struct AST_INTERNAL::ProcessGenerator
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), ast->filename.c_str(), ast->linenum);
+ log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
sw->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -549,12 +549,12 @@ struct AST_INTERNAL::ProcessGenerator
break;
case AST_WIRE:
- log_error("Found wire declaration in block without label at at %s:%d!\n", ast->filename.c_str(), ast->linenum);
+ log_file_error(ast->filename, ast->linenum, "Found wire declaration in block without label!\n");
break;
case AST_PARAMETER:
case AST_LOCALPARAM:
- log_error("Found parameter declaration in block without label at at %s:%d!\n", ast->filename.c_str(), ast->linenum);
+ log_file_error(ast->filename, ast->linenum, "Found parameter declaration in block without label!\n");
break;
case AST_NONE:
@@ -602,7 +602,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (id_ast == NULL && current_scope.count(str))
id_ast = current_scope.at(str);
if (!id_ast)
- log_error("Failed to resolve identifier %s for width detection at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to resolve identifier %s for width detection!\n", str.c_str());
if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM) {
if (id_ast->children.size() > 1 && id_ast->children[1]->range_valid) {
this_width = id_ast->children[1]->range_left - id_ast->children[1]->range_right + 1;
@@ -612,7 +612,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (id_ast->children[0]->type == AST_CONSTANT)
this_width = id_ast->children[0]->bits.size();
else
- log_error("Failed to detect width for parameter %s at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to detect width for parameter %s!\n", str.c_str());
if (children.size() != 0)
range = children[0];
} else if (id_ast->type == AST_WIRE || id_ast->type == AST_AUTOWIRE) {
@@ -624,7 +624,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
// log("---\n");
// id_ast->dumpAst(NULL, "decl> ");
// dumpAst(NULL, "ref> ");
- log_error("Failed to detect width of signal access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to detect width of signal access `%s'!\n", str.c_str());
}
} else {
this_width = id_ast->range_left - id_ast->range_right + 1;
@@ -635,10 +635,10 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
this_width = 32;
} else if (id_ast->type == AST_MEMORY) {
if (!id_ast->children[0]->range_valid)
- log_error("Failed to detect width of memory access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", str.c_str());
this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1;
} else
- log_error("Failed to detect width for identifier %s at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to detect width for identifier %s!\n", str.c_str());
if (range) {
if (range->children.size() == 1)
this_width = 1;
@@ -648,8 +648,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
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);
+ log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
+ str.c_str());
this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
delete left_at_zero_ast;
delete right_at_zero_ast;
@@ -665,7 +665,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
case AST_TO_BITS:
while (children[0]->simplify(true, false, false, 1, -1, false, false) == true) { }
if (children[0]->type != AST_CONSTANT)
- log_error("Left operand of tobits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Left operand of tobits expression is not constant!\n");
children[1]->detectSignWidthWorker(sub_width_hint, sign_hint);
width_hint = max(width_hint, children[0]->bitsAsConst().as_int());
break;
@@ -693,7 +693,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
case AST_REPLICATE:
while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { }
if (children[0]->type != AST_CONSTANT)
- log_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Left operand of replicate expression is not constant!\n");
children[1]->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
width_hint = max(width_hint, children[0]->bitsAsConst().as_int() * sub_width_hint);
sign_hint = false;
@@ -767,7 +767,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (!id2ast->is_signed)
sign_hint = false;
if (!id2ast->children[0]->range_valid)
- log_error("Failed to detect width of memory access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", str.c_str());
this_width = id2ast->children[0]->range_left - id2ast->children[0]->range_right + 1;
width_hint = max(width_hint, this_width);
break;
@@ -777,8 +777,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (GetSize(children) == 1) {
while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { }
if (children[0]->type != AST_CONSTANT)
- log_error("System function %s called with non-const argument at %s:%d!\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s called with non-const argument!\n",
+ RTLIL::unescape_id(str).c_str());
width_hint = max(width_hint, int(children[0]->asInt(true)));
}
break;
@@ -799,8 +799,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
default:
for (auto f : log_files)
current_ast->dumpAst(f, "verilog-ast> ");
- log_error("Don't know how to detect sign and width for %s node at %s:%d!\n",
- type2str(type).c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n",
+ type2str(type).c_str());
}
if (*found_real)
@@ -863,11 +863,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// create an RTLIL::Wire for an AST_WIRE node
case AST_WIRE: {
if (current_module->wires_.count(str) != 0)
- log_error("Re-definition of signal `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Re-definition of signal `%s'!\n",
+ str.c_str());
if (!range_valid)
- log_error("Signal `%s' with non-constant width at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n",
+ str.c_str());
log_assert(range_left >= range_right || (range_left == -1 && range_right == 0));
@@ -881,8 +881,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
wire->attributes[attr.first] = attr.second->asAttrConst();
}
}
@@ -891,16 +891,16 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// create an RTLIL::Memory for an AST_MEMORY node
case AST_MEMORY: {
if (current_module->memories.count(str) != 0)
- log_error("Re-definition of memory `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Re-definition of memory `%s'!\n",
+ str.c_str());
log_assert(children.size() >= 2);
log_assert(children[0]->type == AST_RANGE);
log_assert(children[1]->type == AST_RANGE);
if (!children[0]->range_valid || !children[1]->range_valid)
- log_error("Memory `%s' with non-constant width or size at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n",
+ str.c_str());
RTLIL::Memory *memory = new RTLIL::Memory;
memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
@@ -917,8 +917,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
memory->attributes[attr.first] = attr.second->asAttrConst();
}
}
@@ -937,8 +937,8 @@ 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",
- realvalue, log_signal(sig), filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "converting real value %e to binary %s.\n",
+ realvalue, log_signal(sig));
return sig;
}
@@ -958,25 +958,25 @@ 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_file_warning(filename, linenum, "Identifier `%s' is implicitly declared.\n", str.c_str());
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);
+ log_file_error(filename, linenum, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
}
else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) {
if (id2ast->children[0]->type != AST_CONSTANT)
- log_error("Parameter %s does not evaluate to constant value at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n",
+ str.c_str());
chunk = RTLIL::Const(id2ast->children[0]->bits);
goto use_const_chunk;
}
else if (!id2ast || (id2ast->type != AST_WIRE && id2ast->type != AST_AUTOWIRE &&
id2ast->type != AST_MEMORY) || current_module->wires_.count(str) == 0)
- log_error("Identifier `%s' doesn't map to any signal at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n",
+ str.c_str());
if (id2ast->type == AST_MEMORY)
- log_error("Identifier `%s' does map to an unexpanded memory at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n",
+ str.c_str());
wire = current_module->wires_[str];
chunk.wire = wire;
@@ -994,8 +994,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
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);
+ log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
+ str.c_str());
int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ?
children[0]->children[1]->clone() : children[0]->children[0]->clone());
@@ -1023,11 +1023,11 @@ 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",
- str.c_str(), filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting result bit to undef.\n",
+ str.c_str());
else
- 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);
+ log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting all %d result bits to undef.\n",
+ str.c_str(), chunk.width);
chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width);
} else {
if (chunk.width + chunk.offset > source_width) {
@@ -1040,11 +1040,11 @@ 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",
- str.c_str(), filename.c_str(), linenum, add_undef_bits_lsb);
+ log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d LSB bits to undef.\n",
+ str.c_str(), 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",
- str.c_str(), filename.c_str(), linenum, add_undef_bits_msb);
+ log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d MSB bits to undef.\n",
+ str.c_str(), add_undef_bits_msb);
}
}
}
@@ -1083,7 +1083,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
RTLIL::SigSpec left = children[0]->genRTLIL();
RTLIL::SigSpec right = children[1]->genRTLIL();
if (!left.is_fully_const())
- log_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Left operand of replicate expression is not constant!\n");
int count = left.as_int();
RTLIL::SigSpec sig;
for (int i = 0; i < count; i++)
@@ -1300,6 +1300,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0);
cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0);
+ if (!sign_hint)
+ is_signed = false;
+
return RTLIL::SigSpec(wire);
}
@@ -1319,7 +1322,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
int num_words = 1;
if (type == AST_MEMINIT) {
if (children[2]->type != AST_CONSTANT)
- log_error("Memory init with non-constant word count at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Memory init with non-constant word count!\n");
num_words = int(children[2]->asInt(false));
cell->parameters["\\WORDS"] = RTLIL::Const(num_words);
}
@@ -1376,8 +1379,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -1398,10 +1401,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
new_left.append(left[i]);
new_right.append(right[i]);
}
- log_warning("Ignoring assignment to constant bits at %s:%d:\n"
- " old assignment: %s = %s\n new assignment: %s = %s.\n",
- filename.c_str(), linenum, log_signal(left), log_signal(right),
- log_signal(new_left), log_signal(new_right));
+ log_file_warning(filename, linenum, "Ignoring assignment to constant bits:\n"
+ " old assignment: %s = %s\n new assignment: %s = %s.\n",
+ log_signal(left), log_signal(right),
+ log_signal(new_left), log_signal(new_right));
left = new_left;
right = new_right;
}
@@ -1415,8 +1418,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
int port_counter = 0, para_counter = 0;
if (current_module->count_id(str) != 0)
- log_error("Re-definition of cell `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Re-definition of cell `%s'!\n", str.c_str());
RTLIL::Cell *cell = current_module->addCell(str, "");
cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
@@ -1432,16 +1434,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (child->type == AST_PARASET) {
IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str;
if (child->children[0]->type == AST_REALVALUE) {
- log_warning("Replacing floating point parameter %s.%s = %f with string at %s:%d.\n",
- log_id(cell), log_id(paraname), child->children[0]->realvalue,
- filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "Replacing floating point parameter %s.%s = %f with string.\n",
+ log_id(cell), log_id(paraname), child->children[0]->realvalue);
auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue));
strnode->cloneInto(child->children[0]);
delete strnode;
}
if (child->children[0]->type != AST_CONSTANT)
- log_error("Parameter %s.%s with non-constant value at %s:%d!\n",
- log_id(cell), log_id(paraname), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Parameter %s.%s with non-constant value!\n",
+ log_id(cell), log_id(paraname));
cell->parameters[paraname] = child->children[0]->asParaConst();
continue;
}
@@ -1462,8 +1463,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
}
@@ -1490,19 +1491,19 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
int width = width_hint;
if (GetSize(children) > 1)
- log_error("System function %s got %d arguments, expected 1 or 0 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), GetSize(children), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 0.\n",
+ RTLIL::unescape_id(str).c_str(), GetSize(children));
if (GetSize(children) == 1) {
if (children[0]->type != AST_CONSTANT)
- log_error("System function %s called with non-const argument at %s:%d!\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s called with non-const argument!\n",
+ RTLIL::unescape_id(str).c_str());
width = children[0]->asInt(true);
}
if (width <= 0)
- log_error("Failed to detect width of %s at %s:%d!\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to detect width of %s!\n",
+ RTLIL::unescape_id(str).c_str());
Cell *cell = current_module->addCell(myid, str.substr(1));
cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
@@ -1511,7 +1512,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (attributes.count("\\reg")) {
auto &attr = attributes.at("\\reg");
if (attr->type != AST_CONSTANT)
- log_error("Attribute `reg' with non-constant value at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Attribute `reg' with non-constant value!\n");
cell->attributes["\\reg"] = attr->asAttrConst();
}
@@ -1529,8 +1530,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto f : log_files)
current_ast->dumpAst(f, "verilog-ast> ");
type_name = type2str(type);
- log_error("Don't know how to generate RTLIL code for %s node at %s:%d!\n",
- type_name.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n",
+ type_name.c_str());
}
return RTLIL::SigSpec();
@@ -1560,4 +1561,3 @@ RTLIL::SigSpec AstNode::genWidthRTLIL(int width, const dict<RTLIL::SigBit, RTLIL
}
YOSYS_NAMESPACE_END
-
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index a16fdfeeb..be53e8527 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -177,13 +177,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
// note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
if ((type == AST_FCALL || type == AST_TCALL) && (str == "$strobe" || str == "$monitor" || str == "$time" ||
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);
+ log_file_warning(filename, linenum, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str.c_str());
delete_children();
str = std::string();
}
if ((type == AST_TCALL) && (str == "$display" || str == "$write") && (!current_always || current_always->type != AST_INITIAL)) {
- log_warning("System task `%s' outside initial block is unsupported at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "System task `%s' outside initial block is unsupported.\n", str.c_str());
delete_children();
str = std::string();
}
@@ -195,14 +195,14 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
int nargs = GetSize(children);
if (nargs < 1)
- log_error("System task `%s' got %d arguments, expected >= 1 at %s:%d.\n",
- str.c_str(), int(children.size()), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System task `%s' got %d arguments, expected >= 1.\n",
+ str.c_str(), int(children.size()));
// First argument is the format string
AstNode *node_string = children[0];
while (node_string->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (node_string->type != AST_CONSTANT)
- log_error("Failed to evaluate system task `%s' with non-constant 1st argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str.c_str());
std::string sformat = node_string->bitsAsConst().decode_string();
// Other arguments are placeholders. Process the string as we go through it
@@ -215,7 +215,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
// If there's no next character, that's a problem
if (i+1 >= sformat.length())
- log_error("System task `%s' called with `%%' at end of string at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System task `%s' called with `%%' at end of string.\n", str.c_str());
char cformat = sformat[++i];
@@ -239,13 +239,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
case 'x':
case 'X':
if (next_arg >= GetSize(children))
- log_error("Missing argument for %%%c format specifier in system task `%s' at %s:%d.\n",
- cformat, str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Missing argument for %%%c format specifier in system task `%s'.\n",
+ cformat, str.c_str());
node_arg = children[next_arg++];
while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (node_arg->type != AST_CONSTANT)
- log_error("Failed to evaluate system task `%s' with non-constant argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to evaluate system task `%s' with non-constant argument.\n", str.c_str());
break;
case 'm':
@@ -253,7 +253,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
break;
default:
- log_error("System task `%s' called with invalid/unsupported format specifier at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System task `%s' called with invalid/unsupported format specifier.\n", str.c_str());
break;
}
@@ -374,7 +374,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
continue;
wires_are_incompatible:
if (stage > 1)
- log_error("Incompatible re-declaration of wire %s at %s:%d.\n", node->str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Incompatible re-declaration of wire %s.\n", node->str.c_str());
continue;
}
this_wire_scope[node->str] = node;
@@ -402,7 +402,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_ALWAYS || type == AST_INITIAL)
{
if (current_always != nullptr)
- log_error("Invalid nesting of always blocks and/or initializations at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Invalid nesting of always blocks and/or initializations.\n");
current_always = this;
current_always_clocked = false;
@@ -451,7 +451,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, true) == true)
did_something = true;
if (!children[1]->range_valid)
- log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n");
width_hint = max(width_hint, children[1]->range_left - children[1]->range_right + 1);
}
break;
@@ -695,7 +695,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_DEFPARAM && !children.empty())
{
if (children[0]->type != AST_IDENTIFIER)
- log_error("Module name in defparam at %s:%d contains non-constant expressions!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Module name in defparam contains non-constant expressions!\n");
string modname, paramname = children[0]->str;
@@ -712,13 +712,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
if (pos == std::string::npos)
- log_error("Can't find object for defparam `%s` at %s:%d!\n", RTLIL::unescape_id(paramname).c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname).c_str());
paramname = "\\" + paramname.substr(pos+1);
if (current_scope.at(modname)->type != AST_CELL)
- log_error("Defparam argument `%s . %s` does not match a cell at %s:%d!\n",
- RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Defparam argument `%s . %s` does not match a cell!\n",
+ RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str());
AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL);
paraset->str = paramname;
@@ -732,7 +732,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_PREFIX) {
if (children[0]->type != AST_CONSTANT) {
// dumpAst(NULL, "> ");
- log_error("Index in generate block prefix syntax at %s:%d is not constant!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Index in generate block prefix syntax is not constant!\n");
}
if (children[1]->type == AST_PREFIX)
children[1]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param);
@@ -748,9 +748,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
// evaluate TO_BITS nodes
if (type == AST_TO_BITS) {
if (children[0]->type != AST_CONSTANT)
- log_error("Left operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Left operand of to_bits expression is not constant!\n");
if (children[1]->type != AST_CONSTANT)
- log_error("Right operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Right operand of to_bits expression is not constant!\n");
RTLIL::Const new_value = children[1]->bitsAsConst(children[0]->bitsAsConst().as_int(), children[1]->is_signed);
newNode = mkconst_bits(new_value.bits, children[1]->is_signed);
goto apply_newNode;
@@ -814,7 +814,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
multirange_dimensions.clear();
for (auto range : children[1]->children) {
if (!range->range_valid)
- log_error("Non-constant range on memory decl at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Non-constant range on memory decl.\n");
multirange_dimensions.push_back(min(range->range_left, range->range_right));
multirange_dimensions.push_back(max(range->range_left, range->range_right) - min(range->range_left, range->range_right) + 1);
total_size *= multirange_dimensions.back();
@@ -832,7 +832,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
for (int i = 0; 2*i < GetSize(id2ast->multirange_dimensions); 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);
+ log_file_error(filename, linenum, "Insufficient number of array indices for %s.\n", log_id(str));
AstNode *new_index_expr = children[0]->children[i]->children.at(0)->clone();
@@ -861,12 +861,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_PARAMETER || type == AST_LOCALPARAM) {
if (children.size() > 1 && children[1]->type == AST_RANGE) {
if (!children[1]->range_valid)
- log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n");
int width = std::abs(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",
- children[0]->realvalue, log_signal(constvalue), filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "converting real value %e to binary %s.\n",
+ children[0]->realvalue, log_signal(constvalue));
delete children[0];
children[0] = mkconst_bits(constvalue.bits, sign_hint);
did_something = true;
@@ -924,7 +924,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_IDENTIFIER && children.size() == 2 && children[0]->type == AST_RANGE && children[1]->type == AST_RANGE && !in_lvalue)
{
if (id2ast == NULL || id2ast->type != AST_MEMORY || children[0]->children.size() != 1)
- log_error("Invalid bit-select on memory access at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Invalid bit-select on memory access!\n");
int mem_width, mem_size, addr_bits;
id2ast->meminfo(mem_width, mem_size, addr_bits);
@@ -973,10 +973,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
if (type == AST_WHILE)
- log_error("While loops are only allowed in constant functions at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "While loops are only allowed in constant functions!\n");
if (type == AST_REPEAT)
- log_error("Repeat loops are only allowed in constant functions at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Repeat loops are only allowed in constant functions!\n");
// unroll for loops and generate-for blocks
if ((type == AST_GENFOR || type == AST_FOR) && children.size() != 0)
@@ -991,31 +991,31 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
body_ast = body_ast->children.at(0);
if (init_ast->type != AST_ASSIGN_EQ)
- log_error("Unsupported 1st expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Unsupported 1st expression of generate for-loop!\n");
if (next_ast->type != AST_ASSIGN_EQ)
- log_error("Unsupported 3rd expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Unsupported 3rd expression of generate for-loop!\n");
if (type == AST_GENFOR) {
if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_GENVAR)
- log_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a gen var!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Left hand side of 1st expression of generate for-loop is not a gen var!\n");
if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_GENVAR)
- log_error("Left hand side of 3rd expression of generate for-loop at %s:%d is not a gen var!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n");
} else {
if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_WIRE)
- log_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a register!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Left hand side of 1st expression of generate for-loop is not a register!\n");
if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_WIRE)
- log_error("Left hand side of 3rd expression of generate for-loop at %s:%d is not a register!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Left hand side of 3rd expression of generate for-loop is not a register!\n");
}
if (init_ast->children[0]->id2ast != next_ast->children[0]->id2ast)
- log_error("Incompatible left-hand sides in 1st and 3rd expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n");
// eval 1st expression
AstNode *varbuf = init_ast->children[1]->clone();
while (varbuf->simplify(true, false, false, stage, 32, true, false)) { }
if (varbuf->type != AST_CONSTANT)
- log_error("Right hand side of 1st expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Right hand side of 1st expression of generate for-loop is not constant!\n");
varbuf = new AstNode(AST_LOCALPARAM, varbuf);
varbuf->str = init_ast->children[0]->str;
@@ -1037,7 +1037,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (buf->type != AST_CONSTANT)
- log_error("2nd expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "2nd expression of generate for-loop is not constant!\n");
if (buf->integer == 0) {
delete buf;
@@ -1078,7 +1078,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (buf->simplify(true, false, false, stage, 32, true, false)) { }
if (buf->type != AST_CONSTANT)
- log_error("Right hand side of 3rd expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Right hand side of 3rd expression of generate for-loop is not constant!\n");
delete varbuf->children[0];
varbuf->children[0] = buf;
@@ -1095,8 +1095,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
for (size_t i = 0; i < children.size(); i++)
if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM)
- log_error("Local declaration in unnamed block at %s:%d is an unsupported SystemVerilog feature!\n",
- children[i]->filename.c_str(), children[i]->linenum);
+ log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
}
// transform block with name
@@ -1144,7 +1143,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (buf->type != AST_CONSTANT) {
// for (auto f : log_files)
// dumpAst(f, "verilog-ast> ");
- log_error("Condition for generate if at %s:%d is not constant!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Condition for generate if is not constant!\n");
}
if (buf->asBool() != 0) {
delete buf;
@@ -1185,7 +1184,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (buf->type != AST_CONSTANT) {
// for (auto f : log_files)
// dumpAst(f, "verilog-ast> ");
- log_error("Condition for generate case at %s:%d is not constant!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Condition for generate case is not constant!\n");
}
bool ref_signed = buf->is_signed;
@@ -1219,7 +1218,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (buf->type != AST_CONSTANT) {
// for (auto f : log_files)
// dumpAst(f, "verilog-ast> ");
- log_error("Expression in generate case at %s:%d is not constant!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Expression in generate case is not constant!\n");
}
bool is_selected = RTLIL::const_eq(ref_value, buf->bitsAsConst(), ref_signed && buf->is_signed, ref_signed && buf->is_signed, 1).as_bool();
@@ -1260,7 +1259,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_CELLARRAY)
{
if (!children.at(0)->range_valid)
- log_error("Non-constant array range on cell array at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Non-constant array range on cell array.\n");
newNode = new AstNode(AST_GENBLOCK);
int num = max(children.at(0)->range_left, children.at(0)->range_right) - min(children.at(0)->range_left, children.at(0)->range_right) + 1;
@@ -1271,7 +1270,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
newNode->children.push_back(new_cell);
new_cell->str += stringf("[%d]", idx);
if (new_cell->type == AST_PRIMITIVE) {
- log_error("Cell arrays of primitives are currently not supported at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Cell arrays of primitives are currently not supported.\n");
} else {
log_assert(new_cell->children.at(0)->type == AST_CELLTYPE);
new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str.c_str());
@@ -1285,8 +1284,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_PRIMITIVE)
{
if (children.size() < 2)
- log_error("Insufficient number of arguments for primitive `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n",
+ str.c_str());
std::vector<AstNode*> children_list;
for (auto child : children) {
@@ -1301,8 +1300,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1")
{
if (children_list.size() != 3)
- log_error("Invalid number of arguments for primitive `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n",
+ str.c_str());
std::vector<RTLIL::State> z_const(1, RTLIL::State::Sz);
@@ -1387,8 +1386,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
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);
+ log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
+ str.c_str());
result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
}
did_something = true;
@@ -1645,7 +1644,7 @@ skip_dynamic_range_lvalue_expansion:;
while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
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);
+ log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
@@ -1737,19 +1736,19 @@ skip_dynamic_range_lvalue_expansion:;
int num_steps = 1;
if (GetSize(children) != 1 && GetSize(children) != 2)
- log_error("System function %s got %d arguments, expected 1 or 2 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n",
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
if (!current_always_clocked)
- log_error("System function %s is only allowed in clocked blocks at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n",
+ RTLIL::unescape_id(str).c_str());
if (GetSize(children) == 2)
{
AstNode *buf = children[1]->clone();
while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (buf->type != AST_CONSTANT)
- log_error("Failed to evaluate system function `%s' with non-constant value at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str());
num_steps = buf->asInt(true);
delete buf;
@@ -1805,12 +1804,12 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$stable" || str == "\\$rose" || str == "\\$fell")
{
if (GetSize(children) != 1)
- log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
if (!current_always_clocked)
- log_error("System function %s is only allowed in clocked blocks at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n",
+ RTLIL::unescape_id(str).c_str());
AstNode *present = children.at(0)->clone();
AstNode *past = clone();
@@ -1840,13 +1839,13 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$clog2")
{
if (children.size() != 1)
- log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
AstNode *buf = children[0]->clone();
while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (buf->type != AST_CONSTANT)
- log_error("Failed to evaluate system function `%s' with non-constant value at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str());
RTLIL::Const arg_value = buf->bitsAsConst();
if (arg_value.as_bool())
@@ -1865,12 +1864,12 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$size" || str == "\\$bits")
{
if (str == "\\$bits" && children.size() != 1)
- log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
if (str == "\\$size" && children.size() != 1 && children.size() != 2)
- log_error("System function %s got %d arguments, expected 1 or 2 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n",
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
int dim = 1;
if (str == "\\$size" && children.size() == 2) {
@@ -1893,7 +1892,7 @@ skip_dynamic_range_lvalue_expansion:;
if (id_ast == NULL && current_scope.count(buf->str))
id_ast = current_scope.at(buf->str);
if (!id_ast)
- log_error("Failed to resolve identifier %s for width detection at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to resolve identifier %s for width detection!\n", buf->str.c_str());
if (id_ast->type == AST_MEMORY) {
// We got here only if the argument is a memory
// Otherwise $size() and $bits() return the expression width
@@ -1901,15 +1900,15 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$bits") {
if (mem_range->type == AST_RANGE) {
if (!mem_range->range_valid)
- log_error("Failed to detect width of memory access `%s' at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", buf->str.c_str());
mem_depth = mem_range->range_left - mem_range->range_right + 1;
} else
- log_error("Unknown memory depth AST type in `%s' at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str());
} else {
// $size()
if (mem_range->type == AST_RANGE) {
if (!mem_range->range_valid)
- log_error("Failed to detect width of memory access `%s' at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", buf->str.c_str());
int dims;
if (id_ast->multirange_dimensions.empty())
dims = 1;
@@ -1920,9 +1919,9 @@ skip_dynamic_range_lvalue_expansion:;
else if (dim <= dims) {
width_hint = id_ast->multirange_dimensions[2*dim-1];
} else if ((dim > dims+1) || (dim < 0))
- log_error("Dimension %d out of range in `%s', as it only has dimensions 1..%d at %s:%d!\n", dim, buf->str.c_str(), dims+1, filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Dimension %d out of range in `%s', as it only has dimensions 1..%d!\n", dim, buf->str.c_str(), dims+1);
} else
- log_error("Unknown memory depth AST type in `%s' at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str());
}
}
}
@@ -1943,19 +1942,19 @@ skip_dynamic_range_lvalue_expansion:;
if (func_with_two_arguments) {
if (children.size() != 2)
- log_error("System function %s got %d arguments, expected 2 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s got %d arguments, expected 2.\n",
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
} else {
if (children.size() != 1)
- log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
}
if (children.size() >= 1) {
while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (!children[0]->isConst())
- log_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n",
+ RTLIL::unescape_id(str).c_str());
int child_width_hint = width_hint;
bool child_sign_hint = sign_hint;
children[0]->detectSignWidth(child_width_hint, child_sign_hint);
@@ -1965,8 +1964,8 @@ skip_dynamic_range_lvalue_expansion:;
if (children.size() >= 2) {
while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (!children[1]->isConst())
- log_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n",
+ RTLIL::unescape_id(str).c_str());
int child_width_hint = width_hint;
bool child_sign_hint = sign_hint;
children[1]->detectSignWidth(child_width_hint, child_sign_hint);
@@ -2018,14 +2017,14 @@ skip_dynamic_range_lvalue_expansion:;
for (int i = 2; i < GetSize(dpi_decl->children); i++)
{
if (i-2 >= GetSize(children))
- log_error("Insufficient number of arguments in DPI function call at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Insufficient number of arguments in DPI function call.\n");
argtypes.push_back(RTLIL::unescape_id(dpi_decl->children.at(i)->str));
args.push_back(children.at(i-2)->clone());
while (args.back()->simplify(true, false, false, stage, -1, false, true)) { }
if (args.back()->type != AST_CONSTANT && args.back()->type != AST_REALVALUE)
- log_error("Failed to evaluate DPI function with non-constant argument at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to evaluate DPI function with non-constant argument.\n");
}
newNode = dpi_call(rtype, fname, argtypes, args);
@@ -2037,7 +2036,7 @@ skip_dynamic_range_lvalue_expansion:;
}
if (current_scope.count(str) == 0 || current_scope[str]->type != AST_FUNCTION)
- log_error("Can't resolve function name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Can't resolve function name `%s'.\n", str.c_str());
}
if (type == AST_TCALL)
@@ -2045,26 +2044,26 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "$finish" || str == "$stop")
{
if (!current_always || current_always->type != AST_INITIAL)
- log_error("System task `%s' outside initial block is unsupported at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System task `%s' outside initial block is unsupported.\n", str.c_str());
- log_error("System task `%s' executed at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System task `%s' executed.\n", str.c_str());
}
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);
+ log_file_error(filename, linenum, "System function %s got %d arguments, expected 2-4.\n",
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
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);
+ log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str.c_str());
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);
+ log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str.c_str());
int start_addr = -1, finish_addr = -1;
@@ -2072,7 +2071,7 @@ skip_dynamic_range_lvalue_expansion:;
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);
+ log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str.c_str());
start_addr = int(node_addr->asInt(false));
}
@@ -2080,7 +2079,7 @@ skip_dynamic_range_lvalue_expansion:;
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);
+ log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str.c_str());
finish_addr = int(node_addr->asInt(false));
}
@@ -2106,7 +2105,7 @@ skip_dynamic_range_lvalue_expansion:;
}
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);
+ log_file_error(filename, linenum, "Can't resolve task name `%s'.\n", str.c_str());
}
AstNode *decl = current_scope[str];
@@ -2134,9 +2133,9 @@ skip_dynamic_range_lvalue_expansion:;
}
if (in_param)
- log_error("Non-constant function call in constant expression at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Non-constant function call in constant expression.\n");
if (require_const_eval)
- log_error("Function %s can only be called with constant arguments at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Function %s can only be called with constant arguments.\n", str.c_str());
}
size_t arg_count = 0;
@@ -2253,7 +2252,7 @@ skip_dynamic_range_lvalue_expansion:;
goto tcall_incompatible_wires;
} else {
tcall_incompatible_wires:
- log_error("Incompatible re-declaration of wire %s at %s:%d.\n", child->str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Incompatible re-declaration of wire %s.\n", child->str.c_str());
}
}
}
@@ -2641,7 +2640,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
yosys_input_files.insert(mem_filename);
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_file_error(filename, linenum, "Can not open file `%s` for %s.\n", mem_filename.c_str(), str.c_str());
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;
@@ -2687,7 +2686,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
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);
+ log_file_error(filename, linenum, "Can not parse address `%s` for %s.\n", nptr, str.c_str());
continue;
}
@@ -2943,7 +2942,7 @@ bool AstNode::mem2reg_check(pool<AstNode*> &mem2reg_set)
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);
+ log_file_error(filename, linenum, "Invalid array access.\n");
return true;
}
@@ -3291,16 +3290,16 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
continue;
if (stmt->children.at(1)->type != AST_CONSTANT)
- log_error("Non-constant expression in constant function at %s:%d (called from %s:%d). X\n",
- stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+ log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d). X\n",
+ fcall->filename.c_str(), fcall->linenum);
if (stmt->children.at(0)->type != AST_IDENTIFIER)
- log_error("Unsupported composite left hand side in constant function at %s:%d (called from %s:%d).\n",
- stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+ log_file_error(stmt->filename, stmt->linenum, "Unsupported composite left hand side in constant function (called from %s:%d).\n",
+ fcall->filename.c_str(), fcall->linenum);
if (!variables.count(stmt->children.at(0)->str))
- log_error("Assignment to non-local variable in constant function at %s:%d (called from %s:%d).\n",
- stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+ log_file_error(stmt->filename, stmt->linenum, "Assignment to non-local variable in constant function (called from %s:%d).\n",
+ fcall->filename.c_str(), fcall->linenum);
if (stmt->children.at(0)->children.empty()) {
variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size());
@@ -3339,8 +3338,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
while (cond->simplify(true, false, false, 1, -1, false, true)) { }
if (cond->type != AST_CONSTANT)
- log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
- stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+ log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d).\n",
+ fcall->filename.c_str(), fcall->linenum);
if (cond->asBool()) {
block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
@@ -3360,8 +3359,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
while (num->simplify(true, false, false, 1, -1, false, true)) { }
if (num->type != AST_CONSTANT)
- log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
- stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+ log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d).\n",
+ fcall->filename.c_str(), fcall->linenum);
block->children.erase(block->children.begin());
for (int i = 0; i < num->bitsAsConst().as_int(); i++)
@@ -3398,8 +3397,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
while (cond->simplify(true, false, false, 1, -1, false, true)) { }
if (cond->type != AST_CONSTANT)
- log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
- stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+ log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d).\n",
+ fcall->filename.c_str(), fcall->linenum);
found_match = cond->asBool();
delete cond;
@@ -3428,8 +3427,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
continue;
}
- log_error("Unsupported language construct in constant function at %s:%d (called from %s:%d).\n",
- stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+ log_file_error(stmt->filename, stmt->linenum, "Unsupported language construct in constant function (called from %s:%d).\n",
+ fcall->filename.c_str(), fcall->linenum);
log_abort();
}
@@ -3446,4 +3445,3 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
}
YOSYS_NAMESPACE_END
-
diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc
index e6bb99954..26cd14033 100644
--- a/frontends/blif/blifparse.cc
+++ b/frontends/blif/blifparse.cc
@@ -83,7 +83,9 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
RTLIL::Module *module = nullptr;
RTLIL::Const *lutptr = NULL;
RTLIL::Cell *sopcell = NULL;
+ RTLIL::Cell *lastcell = nullptr;
RTLIL::State lut_default_state = RTLIL::State::Sx;
+ std::string err_reason;
int blif_maxnum = 0, sopmode = -1;
auto blif_wire = [&](const std::string &wire_name) -> Wire*
@@ -159,6 +161,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
if (module != nullptr)
goto error;
module = new RTLIL::Module;
+ lastcell = nullptr;
module->name = RTLIL::escape_id(strtok(NULL, " \t\r\n"));
obj_attributes = &module->attributes;
obj_parameters = nullptr;
@@ -232,6 +235,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
}
module = nullptr;
+ lastcell = nullptr;
obj_attributes = nullptr;
obj_parameters = nullptr;
continue;
@@ -264,6 +268,22 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
continue;
}
+ if (!strcmp(cmd, ".cname"))
+ {
+ char *p = strtok(NULL, " \t\r\n");
+ if (p == NULL)
+ goto error;
+
+ if(lastcell == nullptr || module == nullptr)
+ {
+ err_reason = stringf("No primative object to attach .cname %s.", p);
+ goto error_with_reason;
+ }
+
+ module->rename(lastcell, p);
+ continue;
+ }
+
if (!strcmp(cmd, ".attr") || !strcmp(cmd, ".param")) {
char *n = strtok(NULL, " \t\r\n");
char *v = strtok(NULL, "\r\n");
@@ -281,12 +301,16 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
const_v.bits[i] = v[n-i-1] != '0' ? State::S1 : State::S0;
}
if (!strcmp(cmd, ".attr")) {
- if (obj_attributes == nullptr)
- goto error;
+ if (obj_attributes == nullptr) {
+ err_reason = stringf("No object to attach .attr too.");
+ goto error_with_reason;
+ }
(*obj_attributes)[id_n] = const_v;
} else {
- if (obj_parameters == nullptr)
- goto error;
+ if (obj_parameters == nullptr) {
+ err_reason = stringf("No object to attach .param too.");
+ goto error_with_reason;
+ }
(*obj_parameters)[id_n] = const_v;
}
continue;
@@ -331,6 +355,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
}
}
+ lastcell = cell;
obj_attributes = &cell->attributes;
obj_parameters = &cell->parameters;
continue;
@@ -383,6 +408,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
cell->setPort(it.first, sig);
}
+ lastcell = cell;
obj_attributes = &cell->attributes;
obj_parameters = &cell->parameters;
continue;
@@ -391,7 +417,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
obj_attributes = nullptr;
obj_parameters = nullptr;
- if (!strcmp(cmd, ".barbuf"))
+ if (!strcmp(cmd, ".barbuf") || !strcmp(cmd, ".conn"))
{
char *p = strtok(NULL, " \t\r\n");
if (p == NULL)
@@ -459,6 +485,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
sopcell->setPort("\\A", input_sig);
sopcell->setPort("\\Y", output_sig);
sopmode = -1;
+ lastcell = sopcell;
}
else
{
@@ -469,6 +496,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
cell->setPort("\\Y", output_sig);
lutptr = &cell->parameters.at("\\LUT");
lut_default_state = RTLIL::State::Sx;
+ lastcell = cell;
}
continue;
}
@@ -546,6 +574,8 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
error:
log_error("Syntax error in line %d!\n", line_count);
+error_with_reason:
+ log_error("Syntax error in line %d: %s\n", line_count, err_reason.c_str());
}
struct BlifFrontend : public Frontend {
diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc
index c9b6a54b2..b9e53a4be 100644
--- a/frontends/liberty/liberty.cc
+++ b/frontends/liberty/liberty.cc
@@ -148,7 +148,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack
}
if (0 <= top && stack[top].type == 2) {
- if (next_token.type == '*' || next_token.type == '&' || next_token.type == 0 || next_token.type == '(')
+ if (next_token.type == '*' || next_token.type == '&' || next_token.type == 0 || next_token.type == '(' || next_token.type == '!')
return false;
stack[top].type = 3;
return true;
diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc
index f67337754..b8dd72b98 100644
--- a/frontends/verific/verific.cc
+++ b/frontends/verific/verific.cc
@@ -62,8 +62,11 @@ using namespace Verific;
YOSYS_NAMESPACE_BEGIN
int verific_verbose;
+bool verific_import_pending;
string verific_error_msg;
+vector<string> verific_incdirs, verific_libdirs;
+
void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefile, const char *msg, va_list args)
{
string message_prefix = stringf("VERIFIC-%s [%s] ",
@@ -1613,11 +1616,73 @@ struct VerificExtNets
}
};
+void verific_import(Design *design, std::string top)
+{
+ std::set<Netlist*> nl_todo, nl_done;
+
+ {
+ VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary("work", 1);
+ VeriLibrary *veri_lib = veri_file::GetLibrary("work", 1);
+
+ Array veri_libs, vhdl_libs;
+ if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib);
+ if (veri_lib) veri_libs.InsertLast(veri_lib);
+
+ Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs);
+ Netlist *nl;
+ int i;
+
+ FOREACH_ARRAY_ITEM(netlists, i, nl) {
+ if (top.empty() || nl->Owner()->Name() == top)
+ nl_todo.insert(nl);
+ }
+
+ delete netlists;
+ }
+
+ if (!verific_error_msg.empty())
+ log_error("%s\n", verific_error_msg.c_str());
+
+ VerificExtNets worker;
+ for (auto nl : nl_todo)
+ worker.run(nl);
+
+ while (!nl_todo.empty()) {
+ Netlist *nl = *nl_todo.begin();
+ if (nl_done.count(nl) == 0) {
+ VerificImporter importer(false, false, false, false, false, false);
+ importer.import_netlist(design, nl, nl_todo);
+ }
+ nl_todo.erase(nl);
+ nl_done.insert(nl);
+ }
+
+ veri_file::Reset();
+ vhdl_file::Reset();
+ Libset::Reset();
+ verific_incdirs.clear();
+ verific_libdirs.clear();
+ verific_import_pending = false;
+
+ if (!verific_error_msg.empty())
+ log_error("%s\n", verific_error_msg.c_str());
+}
+
YOSYS_NAMESPACE_END
#endif /* YOSYS_ENABLE_VERIFIC */
PRIVATE_NAMESPACE_BEGIN
+bool check_noverific_env()
+{
+ const char *e = getenv("YOSYS_NOVERIFIC");
+ if (e == nullptr)
+ return false;
+ if (atoi(e) == 0)
+ return false;
+ return true;
+}
+
struct VerificPass : public Pass {
VerificPass() : Pass("verific", "load Verilog and VHDL designs using Verific") { }
virtual void help()
@@ -1632,6 +1697,14 @@ struct VerificPass : public Pass {
log("Files passed to different calls to this command are treated as belonging to\n");
log("different compilation units.\n");
log("\n");
+ log("Additional -D<macro>[=<value>] options may be added after the option indicating\n");
+ log("the language version (and before file names) to set additional verilog defines.\n");
+ log("The macros SYNTHESIS and VERIFIC are defined implicitly.\n");
+ log("\n");
+ log("\n");
+ log(" verific -formal <verilog-file>..\n");
+ log("\n");
+ log("Like -sv, but define FORMAL instead of SYNTHESIS.\n");
log("\n");
log(" verific {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} <vhdl-file>..\n");
log("\n");
@@ -1651,7 +1724,12 @@ struct VerificPass : public Pass {
log("\n");
log(" verific -vlog-define <macro>[=<value>]..\n");
log("\n");
- log("Add Verilog defines. (The macros SYNTHESIS and VERIFIC are defined implicitly.)\n");
+ log("Add Verilog defines.\n");
+ log("\n");
+ log("\n");
+ log(" verific -vlog-undef <macro>..\n");
+ log("\n");
+ log("Remove Verilog defines previously set with -vlog-define.\n");
log("\n");
log("\n");
log(" verific -import [options] <top-module>..\n");
@@ -1708,6 +1786,9 @@ struct VerificPass : public Pass {
#ifdef YOSYS_ENABLE_VERIFIC
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
+ if (check_noverific_env())
+ log_cmd_error("This version of Yosys is built without Verific support.\n");
+
log_header(design, "Executing VERIFIC (loading SystemVerilog and VHDL designs using Verific).\n");
Message::SetConsoleOutput(0);
@@ -1718,8 +1799,9 @@ struct VerificPass : public Pass {
RuntimeFlags::SetVar("veri_extract_dualport_rams", 0);
RuntimeFlags::SetVar("veri_extract_multiport_rams", 1);
RuntimeFlags::SetVar("db_infer_wide_operators", 1);
- veri_file::DefineCmdLineMacro("VERIFIC");
- veri_file::DefineCmdLineMacro("SYNTHESIS");
+
+ // WARNING: instantiating unknown module 'XYZ' (VERI-1063)
+ Message::SetMessageType("VERI-1063", VERIFIC_ERROR);
verific_verbose = 0;
@@ -1739,13 +1821,13 @@ struct VerificPass : public Pass {
if (GetSize(args) > argidx && args[argidx] == "-vlog-incdir") {
for (argidx++; argidx < GetSize(args); argidx++)
- veri_file::AddIncludeDir(args[argidx].c_str());
+ verific_incdirs.push_back(args[argidx]);
goto check_error;
}
if (GetSize(args) > argidx && args[argidx] == "-vlog-libdir") {
for (argidx++; argidx < GetSize(args); argidx++)
- veri_file::AddYDir(args[argidx].c_str());
+ verific_libdirs.push_back(args[argidx]);
goto check_error;
}
@@ -1764,8 +1846,16 @@ struct VerificPass : public Pass {
goto check_error;
}
+ if (GetSize(args) > argidx && args[argidx] == "-vlog-undef") {
+ for (argidx++; argidx < GetSize(args); argidx++) {
+ string name = args[argidx];
+ veri_file::UndefineMacro(name.c_str());
+ }
+ goto check_error;
+ }
+
if (GetSize(args) > argidx && (args[argidx] == "-vlog95" || args[argidx] == "-vlog2k" || args[argidx] == "-sv2005" ||
- args[argidx] == "-sv2009" || args[argidx] == "-sv2012" || args[argidx] == "-sv"))
+ args[argidx] == "-sv2009" || args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal"))
{
Array file_names;
unsigned verilog_mode;
@@ -1778,17 +1868,43 @@ struct VerificPass : public Pass {
verilog_mode = veri_file::SYSTEM_VERILOG_2005;
else if (args[argidx] == "-sv2009")
verilog_mode = veri_file::SYSTEM_VERILOG_2009;
- else if (args[argidx] == "-sv2012" || args[argidx] == "-sv")
+ else if (args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal")
verilog_mode = veri_file::SYSTEM_VERILOG;
else
log_abort();
- for (argidx++; argidx < GetSize(args); argidx++)
- file_names.Insert(args[argidx].c_str());
+ veri_file::DefineMacro("VERIFIC");
+ veri_file::DefineMacro(args[argidx] == "-formal" ? "FORMAL" : "SYNTHESIS");
+
+ for (argidx++; argidx < GetSize(args) && GetSize(args[argidx]) >= 2 && args[argidx].substr(0, 2) == "-D"; argidx++) {
+ std::string name = args[argidx].substr(2);
+ if (args[argidx] == "-D") {
+ if (++argidx >= GetSize(args))
+ break;
+ name = args[argidx];
+ }
+ size_t equal = name.find('=');
+ if (equal != std::string::npos) {
+ string value = name.substr(equal+1);
+ name = name.substr(0, equal);
+ veri_file::DefineMacro(name.c_str(), value.c_str());
+ } else {
+ veri_file::DefineMacro(name.c_str());
+ }
+ }
+
+ for (auto &dir : verific_incdirs)
+ veri_file::AddIncludeDir(dir.c_str());
+ for (auto &dir : verific_libdirs)
+ veri_file::AddYDir(dir.c_str());
+
+ while (argidx < GetSize(args))
+ file_names.Insert(args[argidx++].c_str());
if (!veri_file::AnalyzeMultipleFiles(&file_names, verilog_mode, "work", veri_file::MFCU))
log_cmd_error("Reading Verilog/SystemVerilog sources failed.\n");
+ verific_import_pending = true;
goto check_error;
}
@@ -1797,6 +1913,7 @@ struct VerificPass : public Pass {
for (argidx++; argidx < GetSize(args); argidx++)
if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_87))
log_cmd_error("Reading `%s' in VHDL_87 mode failed.\n", args[argidx].c_str());
+ verific_import_pending = true;
goto check_error;
}
@@ -1805,6 +1922,7 @@ struct VerificPass : public Pass {
for (argidx++; argidx < GetSize(args); argidx++)
if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_93))
log_cmd_error("Reading `%s' in VHDL_93 mode failed.\n", args[argidx].c_str());
+ verific_import_pending = true;
goto check_error;
}
@@ -1813,6 +1931,7 @@ struct VerificPass : public Pass {
for (argidx++; argidx < GetSize(args); argidx++)
if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_2K))
log_cmd_error("Reading `%s' in VHDL_2K mode failed.\n", args[argidx].c_str());
+ verific_import_pending = true;
goto check_error;
}
@@ -1821,6 +1940,7 @@ struct VerificPass : public Pass {
for (argidx++; argidx < GetSize(args); argidx++)
if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_2008))
log_cmd_error("Reading `%s' in VHDL_2008 mode failed.\n", args[argidx].c_str());
+ verific_import_pending = true;
goto check_error;
}
@@ -2031,6 +2151,9 @@ struct VerificPass : public Pass {
veri_file::Reset();
vhdl_file::Reset();
Libset::Reset();
+ verific_incdirs.clear();
+ verific_libdirs.clear();
+ verific_import_pending = false;
goto check_error;
}
@@ -2048,5 +2171,133 @@ struct VerificPass : public Pass {
#endif
} VerificPass;
-PRIVATE_NAMESPACE_END
+struct ReadPass : public Pass {
+ ReadPass() : Pass("read", "load HDL designs") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" read {-vlog95|-vlog2k|-sv2005|-sv2009|-sv2012|-sv|-formal} <verilog-file>..\n");
+ log("\n");
+ log("Load the specified Verilog/SystemVerilog files. (Full SystemVerilog support\n");
+ log("is only available via Verific.)\n");
+ log("\n");
+ log("Additional -D<macro>[=<value>] options may be added after the option indicating\n");
+ log("the language version (and before file names) to set additional verilog defines.\n");
+ log("\n");
+ log("\n");
+ log(" read {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} <vhdl-file>..\n");
+ log("\n");
+ log("Load the specified VHDL files. (Requires Verific.)\n");
+ log("\n");
+ log("\n");
+ log(" read -define <macro>[=<value>]..\n");
+ log("\n");
+ log("Set global Verilog/SystemVerilog defines.\n");
+ log("\n");
+ log("\n");
+ log(" read -undef <macro>..\n");
+ log("\n");
+ log("Unset global Verilog/SystemVerilog defines.\n");
+ log("\n");
+ log("\n");
+ log(" read -incdir <directory>\n");
+ log("\n");
+ log("Add directory to global Verilog/SystemVerilog include directories.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ if (args.size() < 2)
+ log_cmd_error("Missing mode parameter.\n");
+
+ if (args.size() < 3)
+ log_cmd_error("Missing file name parameter.\n");
+
+#ifdef YOSYS_ENABLE_VERIFIC
+ bool use_verific = !check_noverific_env();
+#else
+ bool use_verific = false;
+#endif
+
+ if (args[1] == "-vlog95" || args[1] == "-vlog2k") {
+ if (use_verific) {
+ args[0] = "verific";
+ } else {
+ args[0] = "read_verilog";
+ args.erase(args.begin()+1, args.begin()+2);
+ }
+ Pass::call(design, args);
+ return;
+ }
+
+ if (args[1] == "-sv2005" || args[1] == "-sv2009" || args[1] == "-sv2012" || args[1] == "-sv" || args[1] == "-formal") {
+ if (use_verific) {
+ args[0] = "verific";
+ } else {
+ args[0] = "read_verilog";
+ if (args[1] == "-formal")
+ args.insert(args.begin()+1, std::string());
+ args[1] = "-sv";
+ }
+ Pass::call(design, args);
+ return;
+ }
+
+ if (args[1] == "-vhdl87" || args[1] == "-vhdl93" || args[1] == "-vhdl2k" || args[1] == "-vhdl2008" || args[1] == "-vhdl") {
+ if (use_verific) {
+ args[0] = "verific";
+ Pass::call(design, args);
+ } else {
+ log_cmd_error("This version of Yosys is built without Verific support.\n");
+ }
+ return;
+ }
+
+ if (args[1] == "-define") {
+ if (use_verific) {
+ args[0] = "verific";
+ args[1] = "-vlog-define";
+ Pass::call(design, args);
+ }
+ args[0] = "verilog_defines";
+ args.erase(args.begin()+1, args.begin()+2);
+ for (int i = 1; i < GetSize(args); i++)
+ args[i] = "-D" + args[i];
+ Pass::call(design, args);
+ return;
+ }
+ if (args[1] == "-undef") {
+ if (use_verific) {
+ args[0] = "verific";
+ args[1] = "-vlog-undef";
+ Pass::call(design, args);
+ }
+ args[0] = "verilog_defines";
+ args.erase(args.begin()+1, args.begin()+2);
+ for (int i = 1; i < GetSize(args); i++)
+ args[i] = "-U" + args[i];
+ Pass::call(design, args);
+ return;
+ }
+
+ if (args[1] == "-incdir") {
+ if (use_verific) {
+ args[0] = "verific";
+ args[1] = "-vlog-incdir";
+ Pass::call(design, args);
+ }
+ args[0] = "verilog_defaults";
+ args[1] = "-add";
+ for (int i = 2; i < GetSize(args); i++)
+ args[i] = "-I" + args[i];
+ Pass::call(design, args);
+ return;
+ }
+
+ log_cmd_error("Missing or unsupported mode parameter.\n");
+ }
+} ReadPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/frontends/verific/verific.h b/frontends/verific/verific.h
index 86a743ea1..cbd9314db 100644
--- a/frontends/verific/verific.h
+++ b/frontends/verific/verific.h
@@ -25,6 +25,9 @@ YOSYS_NAMESPACE_BEGIN
extern int verific_verbose;
+extern bool verific_import_pending;
+extern void verific_import(Design *design, std::string top = std::string());
+
extern pool<int> verific_sva_prims;
struct VerificImporter;
diff --git a/frontends/verific/verificsva.cc b/frontends/verific/verificsva.cc
index 4e440b4ca..85b842186 100644
--- a/frontends/verific/verificsva.cc
+++ b/frontends/verific/verificsva.cc
@@ -980,7 +980,6 @@ struct VerificSvaImporter
bool mode_assume = false;
bool mode_cover = false;
bool mode_trigger = false;
- bool eventually = false;
Instance *net_to_ast_driver(Net *n)
{
@@ -1487,6 +1486,72 @@ struct VerificSvaImporter
fsm.getFirstAcceptReject(accept_p, reject_p);
}
+ bool eventually_property(Net *&net, SigBit &trig)
+ {
+ Instance *inst = net_to_ast_driver(net);
+
+ if (inst == nullptr)
+ return false;
+
+ if (clocking.cond_net != nullptr)
+ trig = importer->net_map_at(clocking.cond_net);
+ else
+ trig = State::S1;
+
+ if (inst->Type() == PRIM_SVA_S_EVENTUALLY || inst->Type() == PRIM_SVA_EVENTUALLY)
+ {
+ if (mode_cover || mode_trigger)
+ parser_error(inst);
+
+ net = inst->GetInput();
+ clocking.cond_net = nullptr;
+
+ return true;
+ }
+
+ if (inst->Type() == PRIM_SVA_OVERLAPPED_IMPLICATION ||
+ inst->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION)
+ {
+ Net *antecedent_net = inst->GetInput1();
+ Net *consequent_net = inst->GetInput2();
+
+ Instance *consequent_inst = net_to_ast_driver(consequent_net);
+
+ if (consequent_inst == nullptr)
+ return false;
+
+ if (consequent_inst->Type() != PRIM_SVA_S_EVENTUALLY && consequent_inst->Type() != PRIM_SVA_EVENTUALLY)
+ return false;
+
+ if (mode_cover || mode_trigger)
+ parser_error(consequent_inst);
+
+ int node;
+
+ SvaFsm antecedent_fsm(clocking, trig);
+ node = parse_sequence(antecedent_fsm, antecedent_fsm.createStartNode(), antecedent_net);
+ if (inst->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION) {
+ int next_node = antecedent_fsm.createNode();
+ antecedent_fsm.createEdge(node, next_node);
+ node = next_node;
+ }
+ antecedent_fsm.createLink(node, antecedent_fsm.acceptNode);
+
+ trig = antecedent_fsm.getAccept();
+ net = consequent_inst->GetInput();
+ clocking.cond_net = nullptr;
+
+ if (verific_verbose) {
+ log(" Eventually Antecedent FSM:\n");
+ antecedent_fsm.dump();
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
void parse_property(Net *net, SigBit *accept_p, SigBit *reject_p)
{
Instance *inst = net_to_ast_driver(net);
@@ -1620,10 +1685,46 @@ struct VerificSvaImporter
}
else
{
- if (mode_assert || mode_assume) {
- parse_property(clocking.body_net, nullptr, &reject_bit);
- } else {
- parse_property(clocking.body_net, &accept_bit, nullptr);
+ Net *net = clocking.body_net;
+ SigBit trig;
+
+ if (eventually_property(net, trig))
+ {
+ SigBit sig_a, sig_en = trig;
+ parse_property(net, &sig_a, nullptr);
+
+ // add final FF stage
+
+ SigBit sig_a_q, sig_en_q;
+
+ if (clocking.body_net == nullptr) {
+ sig_a_q = sig_a;
+ sig_en_q = sig_en;
+ } else {
+ sig_a_q = module->addWire(NEW_ID);
+ sig_en_q = module->addWire(NEW_ID);
+ clocking.addDff(NEW_ID, sig_a, sig_a_q, State::S0);
+ clocking.addDff(NEW_ID, sig_en, sig_en_q, State::S0);
+ }
+
+ // generate fair/live cell
+
+ RTLIL::Cell *c = nullptr;
+
+ if (mode_assert) c = module->addLive(root_name, sig_a_q, sig_en_q);
+ if (mode_assume) c = module->addFair(root_name, sig_a_q, sig_en_q);
+
+ importer->import_attributes(c->attributes, root);
+
+ return;
+ }
+ else
+ {
+ if (mode_assert || mode_assume) {
+ parse_property(net, nullptr, &reject_bit);
+ } else {
+ parse_property(net, &accept_bit, nullptr);
+ }
}
}
diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc
index 4a58357bf..7848c626d 100644
--- a/frontends/verilog/const2ast.cc
+++ b/frontends/verilog/const2ast.cc
@@ -49,8 +49,7 @@ static int my_decimal_div_by_two(std::vector<uint8_t> &digits)
int carry = 0;
for (size_t i = 0; i < digits.size(); i++) {
if (digits[i] >= 10)
- log_error("Invalid use of [a-fxz?] in decimal constant at %s:%d.\n",
- current_filename.c_str(), get_line_num());
+ log_file_error(current_filename, get_line_num(), "Invalid use of [a-fxz?] in decimal constant.\n");
digits[i] += carry * 10;
carry = digits[i] % 2;
digits[i] /= 2;
@@ -105,8 +104,8 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
int bits_per_digit = my_ilog2(base-1);
for (auto it = digits.rbegin(), e = digits.rend(); it != e; it++) {
if (*it > (base-1) && *it < 0xf0)
- log_error("Digit larger than %d used in in base-%d constant at %s:%d.\n",
- base-1, base, current_filename.c_str(), get_line_num());
+ log_file_error(current_filename, get_line_num(), "Digit larger than %d used in in base-%d constant.\n",
+ base-1, base);
for (int i = 0; i < bits_per_digit; i++) {
int bitmask = 1 << i;
if (*it == 0xf0)
@@ -238,4 +237,3 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
}
YOSYS_NAMESPACE_END
-
diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc
index 505c94619..be925fea2 100644
--- a/frontends/verilog/verilog_frontend.cc
+++ b/frontends/verilog/verilog_frontend.cc
@@ -42,7 +42,7 @@ static std::list<std::vector<std::string>> verilog_defaults_stack;
static void error_on_dpi_function(AST::AstNode *node)
{
if (node->type == AST::AST_DPI_FUNCTION)
- log_error("Found DPI function %s at %s:%d.\n", node->str.c_str(), node->filename.c_str(), node->linenum);
+ log_file_error(node->filename, node->linenum, "Found DPI function %s.\n", node->str.c_str());
for (auto child : node->children)
error_on_dpi_function(child);
}
@@ -519,13 +519,11 @@ 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);
+ YOSYS_NAMESPACE_PREFIX log_file_error(YOSYS_NAMESPACE_PREFIX AST::current_filename, frontend_verilog_yyget_lineno(),
+ "%s", buffer);
exit(1);
}
-
diff --git a/kernel/log.cc b/kernel/log.cc
index 6d562b9e6..0ee2170a0 100644
--- a/kernel/log.cc
+++ b/kernel/log.cc
@@ -203,7 +203,8 @@ void logv_header(RTLIL::Design *design, const char *format, va_list ap)
log_files.pop_back();
}
-void logv_warning(const char *format, va_list ap)
+static void logv_warning_with_prefix(const char *prefix,
+ const char *format, va_list ap)
{
std::string message = vstringf(format, ap);
bool suppressed = false;
@@ -214,7 +215,7 @@ void logv_warning(const char *format, va_list ap)
if (suppressed)
{
- log("Suppressed warning: %s", message.c_str());
+ log("Suppressed %s%s", prefix, message.c_str());
}
else
{
@@ -224,7 +225,7 @@ void logv_warning(const char *format, va_list ap)
if (log_warnings.count(message))
{
- log("Warning: %s", message.c_str());
+ log("%s%s", prefix, message.c_str());
log_flush();
}
else
@@ -232,7 +233,7 @@ void logv_warning(const char *format, va_list ap)
if (log_errfile != NULL && !log_quiet_warnings)
log_files.push_back(log_errfile);
- log("Warning: %s", message.c_str());
+ log("%s%s", prefix, message.c_str());
log_flush();
if (log_errfile != NULL && !log_quiet_warnings)
@@ -245,49 +246,30 @@ void logv_warning(const char *format, va_list ap)
}
}
-void logv_warning_noprefix(const char *format, va_list ap)
+void logv_warning(const char *format, va_list ap)
{
- std::string message = vstringf(format, ap);
- bool suppressed = false;
-
- for (auto &re : log_nowarn_regexes)
- if (std::regex_search(message, re))
- suppressed = true;
-
- if (suppressed)
- {
- log("%s", message.c_str());
- }
- else
- {
- for (auto &re : log_werror_regexes)
- if (std::regex_search(message, re))
- log_error("%s", message.c_str());
-
- if (log_warnings.count(message))
- {
- log("%s", message.c_str());
- log_flush();
- }
- else
- {
- if (log_errfile != NULL && !log_quiet_warnings)
- log_files.push_back(log_errfile);
-
- log("%s", message.c_str());
- log_flush();
-
- if (log_errfile != NULL && !log_quiet_warnings)
- log_files.pop_back();
+ logv_warning_with_prefix("Warning: ", format, ap);
+}
- log_warnings.insert(message);
- }
+void logv_warning_noprefix(const char *format, va_list ap)
+{
+ logv_warning_with_prefix("", format, ap);
+}
- log_warnings_count++;
- }
+void log_file_warning(const std::string &filename, int lineno,
+ const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ std::string prefix = stringf("%s:%d: Warning: ",
+ filename.c_str(), lineno);
+ logv_warning_with_prefix(prefix.c_str(), format, ap);
+ va_end(ap);
}
-void logv_error(const char *format, va_list ap)
+YS_ATTRIBUTE(noreturn)
+static void logv_error_with_prefix(const char *prefix,
+ const char *format, va_list ap)
{
#ifdef EMSCRIPTEN
auto backup_log_files = log_files;
@@ -302,7 +284,7 @@ void logv_error(const char *format, va_list ap)
f = stderr;
log_last_error = vstringf(format, ap);
- log("ERROR: %s", log_last_error.c_str());
+ log("%s%s", prefix, log_last_error.c_str());
log_flush();
if (log_error_atexit)
@@ -318,6 +300,21 @@ void logv_error(const char *format, va_list ap)
#endif
}
+void logv_error(const char *format, va_list ap)
+{
+ logv_error_with_prefix("ERROR: ", format, ap);
+}
+
+void log_file_error(const string &filename, int lineno,
+ const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ std::string prefix = stringf("%s:%d: ERROR: ",
+ filename.c_str(), lineno);
+ logv_error_with_prefix(prefix.c_str(), format, ap);
+}
+
void log(const char *format, ...)
{
va_list ap;
@@ -636,4 +633,3 @@ dict<std::string, std::pair<std::string, int>> get_coverage_data()
#endif
YOSYS_NAMESPACE_END
-
diff --git a/kernel/log.h b/kernel/log.h
index a2aacfd4d..0b4905c3a 100644
--- a/kernel/log.h
+++ b/kernel/log.h
@@ -73,8 +73,13 @@ YS_NORETURN void logv_error(const char *format, va_list ap) YS_ATTRIBUTE(noretur
void log(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
void log_header(RTLIL::Design *design, const char *format, ...) YS_ATTRIBUTE(format(printf, 2, 3));
void log_warning(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
+
+// Log with filename to report a problem in a source file.
+void log_file_warning(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4));
+
void log_warning_noprefix(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
YS_NORETURN void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn);
+void log_file_error(const string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4), noreturn);
YS_NORETURN void log_cmd_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn);
void log_spacer();
diff --git a/kernel/yosys.cc b/kernel/yosys.cc
index 750a154e6..dca277532 100644
--- a/kernel/yosys.cc
+++ b/kernel/yosys.cc
@@ -825,6 +825,8 @@ void run_frontend(std::string filename, std::string command, std::string *backen
command = "vhdl";
else if (filename.size() > 4 && filename.substr(filename.size()-5) == ".blif")
command = "blif";
+ else if (filename.size() > 5 && filename.substr(filename.size()-6) == ".eblif")
+ command = "blif";
else if (filename.size() > 4 && filename.substr(filename.size()-5) == ".json")
command = "json";
else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")
diff --git a/misc/yosys.proto b/misc/yosys.proto
new file mode 100644
index 000000000..2870176cb
--- /dev/null
+++ b/misc/yosys.proto
@@ -0,0 +1,175 @@
+//
+// yosys -- Yosys Open SYnthesis Suite
+//
+// Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
+//
+// 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.
+//
+
+/// Protobuf definition of Yosys RTLIL dump/restore format for RTL designs.
+
+syntax = "proto3";
+
+package yosys.pb;
+
+// Port direction.
+enum Direction {
+ DIRECTION_INVALID = 0;
+ DIRECTION_INPUT = 1;
+ DIRECTION_OUTPUT = 2;
+ DIRECTION_INOUT = 3;
+}
+
+// A freeform parameter/attribute value.
+message Parameter {
+ oneof value {
+ int64 int = 1;
+ string str = 2;
+ }
+}
+
+// A signal in the design - either a unique identifier for one, or a constant
+// driver (low or high).
+message Signal {
+ // A constant signal driver in the design.
+ enum ConstantDriver {
+ CONSTANT_DRIVER_INVALID = 0;
+ CONSTANT_DRIVER_LOW = 1;
+ CONSTANT_DRIVER_HIGH = 2;
+ CONSTANT_DRIVER_Z = 3;
+ CONSTANT_DRIVER_X = 4;
+ }
+ oneof type {
+ // Signal uniquely identified by ID number.
+ int64 id = 1;
+ // Constant driver.
+ ConstantDriver constant = 2;
+ }
+}
+
+// A vector of signals.
+message BitVector {
+ repeated Signal signal = 1;
+}
+
+// A netlist module.
+message Module {
+ // Freeform attributes.
+ map<string, Parameter> attribute = 1;
+
+ // Named ports in this module.
+ message Port {
+ Direction direction = 1;
+ BitVector bits = 2;
+ }
+ map<string, Port> port = 2;
+
+ // Named cells in this module.
+ message Cell {
+ // Set to true when the name of this cell is automatically created and
+ // likely not of interest for a regular user.
+ bool hide_name = 1;
+ string type = 2;
+ // Set if this module has an AIG model available.
+ string model = 3;
+ // Freeform parameters.
+ map<string, Parameter> parameter = 4;
+ // Freeform attributes.
+ map<string, Parameter> attribute = 5;
+
+ /// Ports of the cell.
+ // Direction of the port, if interface is known.
+ map<string, Direction> port_direction = 6;
+ // Connection of named port to signal(s).
+ map<string, BitVector> connection = 7;
+ }
+ map<string, Cell> cell = 3;
+
+ // Nets in this module.
+ message Netname {
+ // Set to true when the name of this net is automatically created and
+ // likely not of interest for a regular user.
+ bool hide_name = 1;
+ // Signal(s) that make up this net.
+ BitVector bits = 2;
+ // Freeform attributes.
+ map<string, Parameter> attributes = 3;
+ }
+ repeated Netname netname = 4;
+}
+
+// And-Inverter-Graph model.
+message Model {
+ message Node {
+ // Type of AIG node - or, what its' value is.
+ enum Type {
+ TYPE_INVALID = 0;
+ // The node's value is the value of the specified input port bit.
+ TYPE_PORT = 1;
+ // The node's value is the inverted value of the specified input
+ // port bit.
+ TYPE_NPORT = 2;
+ // The node's value is the ANDed value of specified nodes.
+ TYPE_AND = 3;
+ // The node's value is the NANDed value of specified nodes.
+ TYPE_NAND = 4;
+ // The node's value is a constant 1.
+ TYPE_TRUE = 5;
+ // The node's value is a constant 0.
+ TYPE_FALSE = 6;
+ };
+ Type type = 1;
+
+ message Port {
+ // Name of port.
+ string portname = 1;
+ // Bit index in port.
+ int64 bitindex = 2;
+ }
+ message Gate {
+ // Node index of left side of operation.
+ int64 left = 1;
+ // Node index of right side of operation.
+ int64 right = 2;
+ }
+ oneof node {
+ // Set for PORT, NPORT
+ Port port = 2;
+ // Set for AND, NAND.
+ Gate gate = 3;
+ }
+
+ // Set when the node drives given output port(s).
+ message OutPort {
+ // Name of port.
+ string name = 1;
+ // Bit index in port.
+ int64 bit_index = 2;
+ }
+ repeated OutPort out_port = 4;
+ }
+
+ // List of AIG nodes - each is explicitely numbered by its' index in this
+ // array.
+ repeated Node node = 1;
+}
+
+// A Yosys design netlist dumped from RTLIL.
+message Design {
+ // Human-readable freeform 'remark' string.
+ string creator = 1;
+ // List of named modules in design.
+ map<string, Module> modules = 2;
+ // List of named AIG models in design (if AIG export enabled).
+ map<string, Model> models = 3;
+}
diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc
index e52a192db..f1d958a1a 100644
--- a/passes/cmds/stat.cc
+++ b/passes/cmds/stat.cc
@@ -142,7 +142,7 @@ struct statdata_t
}
}
- void log_data()
+ void log_data(RTLIL::IdString mod_name, bool top_mod)
{
log(" Number of wires: %6d\n", num_wires);
log(" Number of wire bits: %6d\n", num_wire_bits);
@@ -163,7 +163,7 @@ struct statdata_t
if (area != 0) {
log("\n");
- log(" Chip area for this module: %f\n", area);
+ log(" Chip area for %smodule '%s': %f\n", (top_mod) ? "top " : "", mod_name.c_str(), area);
}
}
};
@@ -275,7 +275,7 @@ struct StatPass : public Pass {
log("\n");
log("=== %s%s ===\n", RTLIL::id2cstr(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)");
log("\n");
- data.log_data();
+ data.log_data(mod->name, false);
}
if (top_mod != NULL && GetSize(mod_stat) > 1)
@@ -288,7 +288,7 @@ struct StatPass : public Pass {
statdata_t data = hierarchy_worker(mod_stat, top_mod->name, 0);
log("\n");
- data.log_data();
+ data.log_data(top_mod->name, true);
}
log("\n");
diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc
index bfb8e7f95..e61851481 100644
--- a/passes/hierarchy/hierarchy.cc
+++ b/passes/hierarchy/hierarchy.cc
@@ -18,6 +18,7 @@
*/
#include "kernel/yosys.h"
+#include "frontends/verific/verific.h"
#include <stdlib.h>
#include <stdio.h>
#include <set>
@@ -421,6 +422,7 @@ struct HierarchyPass : public Pass {
bool flag_simcheck = false;
bool purge_lib = false;
RTLIL::Module *top_mod = NULL;
+ std::string load_top_mod;
std::vector<std::string> libdirs;
bool auto_top_mode = false;
@@ -511,7 +513,7 @@ struct HierarchyPass : public Pass {
top_mod = design->modules_.count(RTLIL::escape_id(args[argidx])) ? design->modules_.at(RTLIL::escape_id(args[argidx])) : NULL;
}
if (top_mod == NULL)
- log_cmd_error("Module `%s' not found!\n", args[argidx].c_str());
+ load_top_mod = args[argidx];
continue;
}
if (args[argidx] == "-auto-top") {
@@ -522,6 +524,22 @@ struct HierarchyPass : public Pass {
}
extra_args(args, argidx, design, false);
+ if (!load_top_mod.empty()) {
+#ifdef YOSYS_ENABLE_VERIFIC
+ if (verific_import_pending) {
+ verific_import(design, load_top_mod);
+ top_mod = design->module(RTLIL::escape_id(load_top_mod));
+ }
+#endif
+ if (top_mod == NULL)
+ log_cmd_error("Module `%s' not found!\n", load_top_mod.c_str());
+ } else {
+#ifdef YOSYS_ENABLE_VERIFIC
+ if (verific_import_pending)
+ verific_import(design);
+#endif
+ }
+
if (generate_mode) {
generate(design, generate_cells, generate_ports);
return;
diff --git a/passes/sat/Makefile.inc b/passes/sat/Makefile.inc
index 4fcce2fad..8ab0280c0 100644
--- a/passes/sat/Makefile.inc
+++ b/passes/sat/Makefile.inc
@@ -7,4 +7,5 @@ OBJS += passes/sat/miter.o
OBJS += passes/sat/expose.o
OBJS += passes/sat/assertpmux.o
OBJS += passes/sat/clk2fflogic.o
+OBJS += passes/sat/async2sync.o
diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc
new file mode 100644
index 000000000..85933acc2
--- /dev/null
+++ b/passes/sat/async2sync.cc
@@ -0,0 +1,147 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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 Async2syncPass : public Pass {
+ Async2syncPass() : Pass("async2sync", "convert async FF inputs to sync circuits") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" async2sync [options] [selection]\n");
+ log("\n");
+ log("This command replaces async FF inputs with sync circuits emulating the same\n");
+ log("behavior for when the async signals are actually synchronized to the clock.\n");
+ log("\n");
+ log("This pass assumes negative hold time for the async FF inputs. For example when\n");
+ log("a reset deasserts with the clock edge, then the FF output will still drive the\n");
+ log("reset value in the next cycle regardless of the data-in value at the time of\n");
+ log("the clock edge.\n");
+ log("\n");
+ log("Currently only $adff cells are supported by this pass.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ // bool flag_noinit = false;
+
+ log_header(design, "Executing ASYNC2SYNC pass.\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // if (args[argidx] == "-noinit") {
+ // flag_noinit = true;
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ {
+ SigMap sigmap(module);
+ dict<SigBit, State> initbits;
+ pool<SigBit> del_initbits;
+
+ for (auto wire : module->wires())
+ if (wire->attributes.count("\\init") > 0)
+ {
+ Const initval = wire->attributes.at("\\init");
+ SigSpec initsig = sigmap(wire);
+
+ for (int i = 0; i < GetSize(initval) && i < GetSize(initsig); i++)
+ if (initval[i] == State::S0 || initval[i] == State::S1)
+ initbits[initsig[i]] = initval[i];
+ }
+
+ for (auto cell : vector<Cell*>(module->selected_cells()))
+ {
+ if (cell->type.in("$adff"))
+ {
+ // bool clk_pol = cell->parameters["\\CLK_POLARITY"].as_bool();
+ bool arst_pol = cell->parameters["\\ARST_POLARITY"].as_bool();
+ Const arst_val = cell->parameters["\\ARST_VALUE"];
+
+ SigSpec sig_clk = cell->getPort("\\CLK");
+ SigSpec sig_arst = cell->getPort("\\ARST");
+ SigSpec sig_d = cell->getPort("\\D");
+ SigSpec sig_q = cell->getPort("\\Q");
+
+ log("Replacing %s.%s (%s): ARST=%s, D=%s, Q=%s\n",
+ log_id(module), log_id(cell), log_id(cell->type),
+ log_signal(sig_arst), log_signal(sig_d), log_signal(sig_q));
+
+ Const init_val;
+ for (int i = 0; i < GetSize(sig_q); i++) {
+ SigBit bit = sigmap(sig_q[i]);
+ init_val.bits.push_back(initbits.count(bit) ? initbits.at(bit) : State::Sx);
+ del_initbits.insert(bit);
+ }
+
+ Wire *new_d = module->addWire(NEW_ID, GetSize(sig_d));
+ Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q));
+ new_q->attributes["\\init"] = init_val;
+
+ if (arst_pol) {
+ module->addMux(NEW_ID, sig_d, arst_val, sig_arst, new_d);
+ module->addMux(NEW_ID, new_q, arst_val, sig_arst, sig_q);
+ } else {
+ module->addMux(NEW_ID, arst_val, sig_d, sig_arst, new_d);
+ module->addMux(NEW_ID, arst_val, new_q, sig_arst, sig_q);
+ }
+
+ cell->setPort("\\D", new_d);
+ cell->setPort("\\Q", new_q);
+ cell->unsetPort("\\ARST");
+ cell->unsetParam("\\ARST_POLARITY");
+ cell->unsetParam("\\ARST_VALUE");
+ cell->type = "$dff";
+ continue;
+ }
+ }
+
+ for (auto wire : module->wires())
+ if (wire->attributes.count("\\init") > 0)
+ {
+ bool delete_initattr = true;
+ Const initval = wire->attributes.at("\\init");
+ SigSpec initsig = sigmap(wire);
+
+ for (int i = 0; i < GetSize(initval) && i < GetSize(initsig); i++)
+ if (del_initbits.count(initsig[i]) > 0)
+ initval[i] = State::Sx;
+ else if (initval[i] != State::Sx)
+ delete_initattr = false;
+
+ if (delete_initattr)
+ wire->attributes.erase("\\init");
+ else
+ wire->attributes.at("\\init") = initval;
+ }
+ }
+ }
+} Async2syncPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index 140a9f892..4faa0ab00 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -35,6 +35,7 @@ OBJS += passes/techmap/insbuf.o
OBJS += passes/techmap/attrmvcp.o
OBJS += passes/techmap/attrmap.o
OBJS += passes/techmap/zinit.o
+OBJS += passes/techmap/dff2dffs.o
endif
GENFILES += passes/techmap/techmap.inc
@@ -57,4 +58,3 @@ yosys-filterlib$(EXE): passes/techmap/filterlib.o
$(Q) mkdir -p $(dir $@)
$(P) $(LD) -o yosys-filterlib$(EXE) $(LDFLAGS) $^ $(LDLIBS)
endif
-
diff --git a/passes/techmap/deminout.cc b/passes/techmap/deminout.cc
index ed4e45762..0b8fd5246 100644
--- a/passes/techmap/deminout.cc
+++ b/passes/techmap/deminout.cc
@@ -57,7 +57,7 @@ struct DeminoutPass : public Pass {
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
- pool<SigBit> bits_written, bits_used, bits_inout;
+ pool<SigBit> bits_written, bits_used, bits_inout, bits_tribuf;
dict<SigBit, int> bits_numports;
for (auto wire : module->wires())
@@ -82,6 +82,25 @@ struct DeminoutPass : public Pass {
if (cellport_in)
for (auto bit : sigmap(conn.second))
bits_used.insert(bit);
+
+ if (conn.first == "\\Y" && cell->type.in("$mux", "$pmux", "$_MUX_", "$_TBUF_"))
+ {
+ bool tribuf = (cell->type == "$_TBUF_");
+
+ if (!tribuf) {
+ for (auto &c : cell->connections()) {
+ if (!c.first.in("\\A", "\\B"))
+ continue;
+ for (auto b : sigmap(c.second))
+ if (b == State::Sz)
+ tribuf = true;
+ }
+ }
+
+ if (tribuf)
+ for (auto bit : sigmap(conn.second))
+ bits_tribuf.insert(bit);
+ }
}
for (auto wire : module->selected_wires())
@@ -95,10 +114,15 @@ struct DeminoutPass : public Pass {
if (bits_numports[bit] > 1 || bits_inout.count(bit))
new_input = true, new_output = true;
- if (bits_written.count(bit))
+ if (bits_written.count(bit)) {
new_output = true;
- else if (bits_used.count(bit))
- new_input = true;
+ if (bits_tribuf.count(bit))
+ goto tribuf_bit;
+ } else {
+ tribuf_bit:
+ if (bits_used.count(bit))
+ new_input = true;
+ }
}
if (new_input != new_output) {
diff --git a/passes/techmap/dff2dffe.cc b/passes/techmap/dff2dffe.cc
index 1b8920bb7..4d515f174 100644
--- a/passes/techmap/dff2dffe.cc
+++ b/passes/techmap/dff2dffe.cc
@@ -279,8 +279,9 @@ struct Dff2dffePass : public Pass {
log(" -direct-match <pattern>\n");
log(" like -direct for all DFF cell types matching the expression.\n");
log(" this will use $__DFFE_* as <external_gate_type> matching the\n");
- log(" internal gate type $_DFF_*_, except for $_DFF_[NP]_, which is\n");
- log(" converted to $_DFFE_[NP]_.\n");
+ log(" internal gate type $_DFF_*_, and $__DFFSE_* for those matching\n");
+ log(" $_DFFS_*_, except for $_DFF_[NP]_, which is converted to \n");
+ log(" $_DFFE_[NP]_.\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
@@ -315,6 +316,15 @@ struct Dff2dffePass : public Pass {
if (patmatch(pattern, "$_DFF_PN1_")) found_match = true, direct_dict["$_DFF_PN1_"] = "$__DFFE_PN1";
if (patmatch(pattern, "$_DFF_PP0_")) found_match = true, direct_dict["$_DFF_PP0_"] = "$__DFFE_PP0";
if (patmatch(pattern, "$_DFF_PP1_")) found_match = true, direct_dict["$_DFF_PP1_"] = "$__DFFE_PP1";
+
+ if (patmatch(pattern, "$__DFFS_NN0_")) found_match = true, direct_dict["$__DFFS_NN0_"] = "$__DFFSE_NN0";
+ if (patmatch(pattern, "$__DFFS_NN1_")) found_match = true, direct_dict["$__DFFS_NN1_"] = "$__DFFSE_NN1";
+ if (patmatch(pattern, "$__DFFS_NP0_")) found_match = true, direct_dict["$__DFFS_NP0_"] = "$__DFFSE_NP0";
+ if (patmatch(pattern, "$__DFFS_NP1_")) found_match = true, direct_dict["$__DFFS_NP1_"] = "$__DFFSE_NP1";
+ if (patmatch(pattern, "$__DFFS_PN0_")) found_match = true, direct_dict["$__DFFS_PN0_"] = "$__DFFSE_PN0";
+ if (patmatch(pattern, "$__DFFS_PN1_")) found_match = true, direct_dict["$__DFFS_PN1_"] = "$__DFFSE_PN1";
+ if (patmatch(pattern, "$__DFFS_PP0_")) found_match = true, direct_dict["$__DFFS_PP0_"] = "$__DFFSE_PP0";
+ if (patmatch(pattern, "$__DFFS_PP1_")) found_match = true, direct_dict["$__DFFS_PP1_"] = "$__DFFSE_PP1";
if (!found_match)
log_cmd_error("No cell types matched pattern '%s'.\n", pattern);
continue;
diff --git a/passes/techmap/dff2dffs.cc b/passes/techmap/dff2dffs.cc
new file mode 100644
index 000000000..0bfbdc965
--- /dev/null
+++ b/passes/techmap/dff2dffs.cc
@@ -0,0 +1,142 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 David Shah <dave@ds0.me>
+ *
+ * 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 Dff2dffsPass : public Pass {
+ Dff2dffsPass() : Pass("dff2dffs", "process sync set/reset with SR over CE priority") { }
+ virtual void help()
+ {
+ log("\n");
+ log(" dff2dffs [options] [selection]\n");
+ log("\n");
+ log("Merge synchronous set/reset $_MUX_ cells to create $__DFFS_[NP][NP][01], to be run before\n");
+ log("dff2dffe for SR over CE priority.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ log_header(design, "Executing dff2dffs pass (merge synchronous set/reset into FF cells).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // if (args[argidx] == "-singleton") {
+ // singleton_mode = true;
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ pool<IdString> dff_types;
+ dff_types.insert("$_DFF_N_");
+ dff_types.insert("$_DFF_P_");
+
+ for (auto module : design->selected_modules())
+ {
+ log("Merging set/reset $_MUX_ cells into DFFs in %s.\n", log_id(module));
+
+ SigMap sigmap(module);
+ dict<SigBit, Cell*> sr_muxes;
+ vector<Cell*> ff_cells;
+
+ for (auto cell : module->selected_cells())
+ {
+ if (dff_types.count(cell->type)) {
+ ff_cells.push_back(cell);
+ continue;
+ }
+
+ if (cell->type != "$_MUX_")
+ continue;
+
+ SigBit bit_a = sigmap(cell->getPort("\\A"));
+ SigBit bit_b = sigmap(cell->getPort("\\B"));
+
+ if (bit_a.wire == nullptr || bit_b.wire == nullptr)
+ sr_muxes[sigmap(cell->getPort("\\Y"))] = cell;
+ }
+
+ for (auto cell : ff_cells)
+ {
+ SigSpec sig_d = cell->getPort("\\D");
+
+ if (GetSize(sig_d) < 1)
+ continue;
+
+ SigBit bit_d = sigmap(sig_d[0]);
+
+ if (sr_muxes.count(bit_d) == 0)
+ continue;
+
+ Cell *mux_cell = sr_muxes.at(bit_d);
+ SigBit bit_a = sigmap(mux_cell->getPort("\\A"));
+ SigBit bit_b = sigmap(mux_cell->getPort("\\B"));
+ SigBit bit_s = sigmap(mux_cell->getPort("\\S"));
+
+ log(" Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell),
+ log_signal(bit_a), log_signal(bit_b), log_signal(bit_s), log_id(cell), log_id(cell->type));
+
+ SigBit sr_val, sr_sig;
+ bool invert_sr;
+ sr_sig = bit_s;
+ if (bit_a.wire == nullptr) {
+ bit_d = bit_b;
+ sr_val = bit_a;
+ invert_sr = true;
+ } else {
+ log_assert(bit_b.wire == nullptr);
+ bit_d = bit_a;
+ sr_val = bit_b;
+ invert_sr = false;
+ }
+
+ if (sr_val == State::S1) {
+ if (cell->type == "$_DFF_N_") {
+ if (invert_sr) cell->type = "$__DFFS_NN1_";
+ else cell->type = "$__DFFS_NP1_";
+ } else {
+ log_assert(cell->type == "$_DFF_P_");
+ if (invert_sr) cell->type = "$__DFFS_PN1_";
+ else cell->type = "$__DFFS_PP1_";
+ }
+ } else {
+ if (cell->type == "$_DFF_N_") {
+ if (invert_sr) cell->type = "$__DFFS_NN0_";
+ else cell->type = "$__DFFS_NP0_";
+ } else {
+ log_assert(cell->type == "$_DFF_P_");
+ if (invert_sr) cell->type = "$__DFFS_PN0_";
+ else cell->type = "$__DFFS_PP0_";
+ }
+ }
+ cell->setPort("\\R", sr_sig);
+ cell->setPort("\\D", bit_d);
+ }
+ }
+ }
+} Dff2dffsPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/extract_reduce.cc b/passes/techmap/extract_reduce.cc
index cc21c8665..0ce596fda 100644
--- a/passes/techmap/extract_reduce.cc
+++ b/passes/techmap/extract_reduce.cc
@@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include <deque>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc
new file mode 100644
index 000000000..9d3247347
--- /dev/null
+++ b/techlibs/ecp5/Makefile.inc
@@ -0,0 +1,8 @@
+
+OBJS += techlibs/ecp5/synth_ecp5.o
+
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/drams_map.v))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dram.txt))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v))
diff --git a/techlibs/ecp5/arith_map.v b/techlibs/ecp5/arith_map.v
new file mode 100644
index 000000000..1094c5f8a
--- /dev/null
+++ b/techlibs/ecp5/arith_map.v
@@ -0,0 +1,79 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 David Shah <dave@ds0.me>
+ *
+ * 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 = "$alu" *)
+module _80_ecp5_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));
+
+ function integer round_up2;
+ input integer N;
+ begin
+ round_up2 = ((N + 1) / 2) * 2;
+ end
+ endfunction
+
+ localparam Y_WIDTH2 = round_up2(Y_WIDTH);
+
+ wire [Y_WIDTH2-1:0] AA = A_buf;
+ wire [Y_WIDTH2-1:0] BB = BI ? ~B_buf : B_buf;
+ wire [Y_WIDTH2-1:0] C = {CO, CI};
+ wire [Y_WIDTH2-1:0] FCO, Y1;
+
+ genvar i;
+ generate for (i = 0; i < Y_WIDTH2; i = i + 2) begin:slice
+ CCU2C #(
+ .INIT0(16'b0110011010101010),
+ .INIT1(16'b0110011010101010),
+ .INJECT1_0("NO"),
+ .INJECT1_1("NO")
+ ) ccu2c_i (
+ .CIN(C[i]),
+ .A0(AA[i]), .B0(BB[i]), .C0(1'b0), .D0(1'b1),
+ .A1(AA[i+1]), .B1(BB[i+1]), .C1(1'b0), .D1(1'b1),
+ .S0(Y[i]), .S1(Y1[i]),
+ .COUT(FCO[i])
+ );
+
+ assign CO[i] = (AA[i] && BB[i]) || (C[i] && (AA[i] || BB[i]));
+ if (i+1 < Y_WIDTH) begin
+ assign CO[i+1] = FCO[i];
+ assign Y[i+1] = Y1[i];
+ end
+ end endgenerate
+
+ assign X = AA ^ BB;
+endmodule
diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v
new file mode 100644
index 000000000..48162a4dc
--- /dev/null
+++ b/techlibs/ecp5/cells_map.v
@@ -0,0 +1,135 @@
+module \$_DFF_N_ (input D, C, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+module \$_DFF_P_ (input D, C, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+
+module \$_DFFE_NN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+module \$_DFFE_PN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+
+module \$_DFFE_NP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+module \$_DFFE_PP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+
+module \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$_DFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$__DFFS_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$__DFFE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$__DFFE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$__DFFSE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$__DFFSE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+`ifndef NO_LUT
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+
+ input [WIDTH-1:0] A;
+ output Y;
+
+ generate
+ if (WIDTH == 1) begin
+ LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(A[0]), .B(1'b0), .C(1'b0), .D(1'b0));
+ end else
+ if (WIDTH == 2) begin
+ LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(A[0]), .B(A[1]), .C(1'b0), .D(1'b0));
+ end else
+ if (WIDTH == 3) begin
+ LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(1'b0));
+ end else
+ if (WIDTH == 4) begin
+ LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ `ifndef NO_PFUMUX
+ end else
+ if (WIDTH == 5) begin
+ wire f0, f1;
+ LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(Y));
+ end else
+ if (WIDTH == 6) begin
+ wire f0, f1, f2, f3, g0, g1;
+ LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+
+ LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+
+ PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0));
+ PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1));
+ L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[5]), .Z(Y));
+ end else
+ if (WIDTH == 7) begin
+ wire f0, f1, f2, f3, f4, f5, f6, f7, g0, g1, g2, g3, h0, h1;
+ LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+
+ LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+
+ LUT4 #(.INIT(LUT[79:64])) lut4 (.Z(f4),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(LUT[95:80])) lut5 (.Z(f5),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+
+ LUT4 #(.INIT(LUT[111: 96])) lut6 (.Z(f6),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(LUT[127:112])) lut7 (.Z(f7),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+
+ PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0));
+ PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1));
+ PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[4]), .Z(g2));
+ PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[4]), .Z(g3));
+ L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[5]), .Z(h0));
+ L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[5]), .Z(h1));
+ L6MUX21 mux7 (.D0(h0), .D1(h1), .SD(A[6]), .Z(Y));
+ `endif
+ end else begin
+ wire _TECHMAP_FAIL_ = 1;
+ end
+ endgenerate
+endmodule
+`endif
diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v
new file mode 100644
index 000000000..1700694e8
--- /dev/null
+++ b/techlibs/ecp5/cells_sim.v
@@ -0,0 +1,448 @@
+// ---------------------------------------
+
+module LUT4(input A, B, C, D, output Z);
+ parameter [15:0] INIT = 16'h0000;
+ wire [7:0] s3 = D ? INIT[15:8] : INIT[7:0];
+ wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
+ wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
+ assign Z = A ? s1[1] : s1[0];
+endmodule
+
+// ---------------------------------------
+
+module L6MUX21 (input D0, D1, SD, output Z);
+ assign Z = SD ? D1 : D0;
+endmodule
+
+// ---------------------------------------
+
+module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1,
+ output S0, S1, COUT);
+
+ parameter [15:0] INIT0 = 16'h0000;
+ parameter [15:0] INIT1 = 16'h0000;
+ parameter INJECT1_0 = "YES";
+ parameter INJECT1_1 = "YES";
+
+ // First half
+ wire LUT4_0, LUT2_0;
+ LUT4 #(.INIT(INIT0)) lut4_0(.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0));
+ LUT2 #(.INIT(INIT0[3:0])) lut2_0(.A(A0), .B(B0), .Z(LUT2_0));
+
+ wire gated_cin_0 = (INJECT1_0 == "YES") ? 1'b0 : CIN;
+ assign S0 = LUT4_0 ^ gated_cin_0;
+
+ wire gated_lut2_0 = (INJECT1_0 == "YES") ? 1'b0 : LUT2_0;
+ wire cout_0 = (~LUT4_0 & gated_lut2_0) | (LUT4_0 & CIN);
+
+ // Second half
+ wire LUT4_1, LUT2_1;
+ LUT4 #(.INIT(INIT1)) lut4_1(.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1));
+ LUT2 #(.INIT(INIT1[3:0])) lut2_1(.A(A1), .B(B1), .Z(LUT2_1));
+
+ wire gated_cin_1 = (INJECT1_1 == "YES") ? 1'b0 : cout_0;
+ assign S1 = LUT4_1 ^ gated_cin_1;
+
+ wire gated_lut2_1 = (INJECT1_1 == "YES") ? 1'b0 : LUT2_1;
+ assign COUT = (~LUT4_1 & gated_lut2_1) | (LUT4_1 & cout_0);
+
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_RAM16X2 (
+ input DI0, DI1,
+ input WAD0, WAD1, WAD2, WAD3,
+ input WRE, WCK,
+ input RAD0, RAD1, RAD2, RAD3,
+ output DO0, DO1
+);
+ parameter WCKMUX = "WCK";
+ parameter WREMUX = "WRE";
+ parameter INITVAL_0 = 16'h0000;
+ parameter INITVAL_1 = 16'h0000;
+
+ reg [1:0] mem[15:0];
+
+ integer i;
+ initial begin
+ for (i = 0; i < 16; i = i + 1)
+ mem[i] <= {INITVAL_1[i], INITVAL_0[i]};
+ end
+
+ wire muxwck = (WCKMUX == "INV") ? ~WCK : WCK;
+
+ reg muxwre;
+ always @(*)
+ case (WREMUX)
+ "1": muxwre = 1'b1;
+ "0": muxwre = 1'b0;
+ "INV": muxwre = ~WRE;
+ default: muxwre = WRE;
+ endcase
+
+
+ always @(posedge muxwck)
+ if (muxwre)
+ mem[{WAD3, WAD2, WAD1, WAD0}] <= {DI1, DI0};
+
+ assign {DO1, DO0} = mem[{RAD3, RAD2, RAD1, RAD0}];
+endmodule
+
+// ---------------------------------------
+
+module PFUMX (input ALUT, BLUT, C0, output Z);
+ assign Z = C0 ? ALUT : BLUT;
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_DPR16X4 (
+ input [3:0] DI,
+ input [3:0] WAD,
+ input WRE, WCK,
+ input [3:0] RAD,
+ output [3:0] DO
+);
+ parameter WCKMUX = "WCK";
+ parameter WREMUX = "WRE";
+ parameter [63:0] INITVAL = 64'h0000000000000000;
+
+ reg [3:0] mem[15:0];
+
+ integer i;
+ initial begin
+ for (i = 0; i < 16; i = i + 1)
+ mem[i] <= {INITVAL[i+3], INITVAL[i+2], INITVAL[i+1], INITVAL[i]};
+ end
+
+ wire muxwck = (WCKMUX == "INV") ? ~WCK : WCK;
+
+ reg muxwre;
+ always @(*)
+ case (WREMUX)
+ "1": muxwre = 1'b1;
+ "0": muxwre = 1'b0;
+ "INV": muxwre = ~WRE;
+ default: muxwre = WRE;
+ endcase
+
+ always @(posedge muxwck)
+ if (muxwre)
+ mem[WAD] <= DI;
+
+ assign DO = mem[RAD];
+endmodule
+
+// ---------------------------------------
+
+module DPR16X4C (
+ input [3:0] DI,
+ input WCK, WRE,
+ input [3:0] RAD,
+ input [3:0] WAD,
+ output [3:0] DO
+);
+ // For legacy Lattice compatibility, INITIVAL is a hex
+ // string rather than a numeric parameter
+ parameter INITVAL = "0x0000000000000000";
+
+ function [63:0] convert_initval;
+ input [143:0] hex_initval;
+ reg done;
+ reg [63:0] temp;
+ reg [7:0] char;
+ integer i;
+ begin
+ done = 1'b0;
+ temp = 0;
+ for (i = 0; i < 16; i = i + 1) begin
+ if (!done) begin
+ char = hex_initval[8*i +: 8];
+ if (char == "x") begin
+ done = 1'b1;
+ end else begin
+ if (char >= "0" && char <= "9")
+ temp[4*i +: 4] = char - "0";
+ else if (char >= "A" && char <= "F")
+ temp[4*i +: 4] = 10 + char - "A";
+ else if (char >= "a" && char <= "f")
+ temp[4*i +: 4] = 10 + char - "a";
+ end
+ end
+ end
+ convert_initval = temp;
+ end
+ endfunction
+
+ localparam conv_initval = convert_initval(INITVAL);
+
+ reg [3:0] ram[0:15];
+ integer i;
+ initial begin
+ for (i = 0; i < 15; i = i + 1) begin
+ ram[i] <= conv_initval[4*i +: 4];
+ end
+ end
+
+ always @(posedge WCK)
+ if (WRE)
+ ram[WAD] <= DI;
+
+ assign DO = ram[RAD];
+
+endmodule
+
+// ---------------------------------------
+
+module LUT2(input A, B, output Z);
+ parameter [3:0] INIT = 4'h0;
+ wire [1:0] s1 = B ? INIT[ 3:2] : INIT[1:0];
+ assign Z = A ? s1[1] : s1[0];
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q);
+ parameter GSR = "ENABLED";
+ parameter [127:0] CEMUX = "1";
+ parameter CLKMUX = "CLK";
+ parameter LSRMUX = "LSR";
+ parameter SRMODE = "LSR_OVER_CE";
+ parameter REGSET = "RESET";
+
+ reg muxce;
+ always @(*)
+ case (CEMUX)
+ "1": muxce = 1'b1;
+ "0": muxce = 1'b0;
+ "INV": muxce = ~CE;
+ default: muxce = CE;
+ endcase
+
+ wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
+ wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
+
+ localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0;
+
+ initial Q = srval;
+
+ generate
+ if (SRMODE == "ASYNC") begin
+ always @(posedge muxclk, posedge muxlsr)
+ if (muxlsr)
+ Q <= srval;
+ else if (muxce)
+ Q <= DI;
+ end else begin
+ always @(posedge muxclk)
+ if (muxlsr)
+ Q <= srval;
+ else if (muxce)
+ Q <= DI;
+ end
+ endgenerate
+endmodule
+
+// ---------------------------------------
+
+module OBZ(input I, T, output O);
+assign O = T ? 1'bz : I;
+endmodule
+
+// ---------------------------------------
+
+module IB(input I, output O);
+assign O = I;
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_IO(
+ inout B,
+ input I,
+ input T,
+ output O
+);
+ parameter DIR = "INPUT";
+
+ generate
+ if (DIR == "INPUT") begin
+ assign B = 1'bz;
+ assign O = B;
+ end else if (DIR == "OUTPUT") begin
+ assign B = T ? 1'bz : I;
+ assign O = 1'bx;
+ end else if (DIR == "INOUT") begin
+ assign B = T ? 1'bz : I;
+ assign O = B;
+ end else begin
+ ERROR_UNKNOWN_IO_MODE error();
+ end
+ endgenerate
+
+endmodule
+
+// ---------------------------------------
+
+module OB(input I, output O);
+assign O = I;
+endmodule
+
+// ---------------------------------------
+
+module BB(input I, T, output O, inout B);
+assign B = T ? 1'bz : I;
+assign O = B;
+endmodule
+
+// ---------------------------------------
+
+module INV(input A, output Z);
+ assign Z = !A;
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_SLICE(
+ input A0, B0, C0, D0,
+ input A1, B1, C1, D1,
+ input M0, M1,
+ input FCI, FXA, FXB,
+
+ input CLK, LSR, CE,
+ input DI0, DI1,
+
+ input WD0, WD1,
+ input WAD0, WAD1, WAD2, WAD3,
+ input WRE, WCK,
+
+ output F0, Q0,
+ output F1, Q1,
+ output FCO, OFX0, OFX1,
+
+ output WDO0, WDO1, WDO2, WDO3,
+ output WADO0, WADO1, WADO2, WADO3
+);
+
+ parameter MODE = "LOGIC";
+ parameter GSR = "ENABLED";
+ parameter SRMODE = "LSR_OVER_CE";
+ parameter [127:0] CEMUX = "1";
+ parameter CLKMUX = "CLK";
+ parameter LSRMUX = "LSR";
+ parameter LUT0_INITVAL = 16'h0000;
+ parameter LUT1_INITVAL = 16'h0000;
+ parameter REG0_SD = "0";
+ parameter REG1_SD = "0";
+ parameter REG0_REGSET = "RESET";
+ parameter REG1_REGSET = "RESET";
+ parameter [127:0] CCU2_INJECT1_0 = "NO";
+ parameter [127:0] CCU2_INJECT1_1 = "NO";
+ parameter WREMUX = "WRE";
+
+ function [15:0] permute_initval;
+ input [15:0] initval;
+ integer i;
+ begin
+ for (i = 0; i < 16; i = i + 1) begin
+ permute_initval[{i[0], i[2], i[1], i[3]}] = initval[i];
+ end
+ end
+ endfunction
+
+ generate
+ if (MODE == "LOGIC") begin
+ // LUTs
+ LUT4 #(
+ .INIT(LUT0_INITVAL)
+ ) lut4_0 (
+ .A(A0), .B(B0), .C(C0), .D(D0),
+ .Z(F0)
+ );
+ LUT4 #(
+ .INIT(LUT1_INITVAL)
+ ) lut4_1 (
+ .A(A1), .B(B1), .C(C1), .D(D1),
+ .Z(F1)
+ );
+ // LUT expansion muxes
+ PFUMX lut5_mux (.ALUT(F1), .BLUT(F0), .C0(M0), .Z(OFX0));
+ L6MUX21 lutx_mux (.D0(FXA), .D1(FXB), .SD(M1), .Z(OFX1));
+ end else if (MODE == "CCU2") begin
+ CCU2C #(
+ .INIT0(LUT0_INITVAL),
+ .INIT1(LUT1_INITVAL),
+ .INJECT1_0(CCU2_INJECT1_0),
+ .INJECT1_1(CCU2_INJECT1_1)
+ ) ccu2c_i (
+ .CIN(FCI),
+ .A0(A0), .B0(B0), .C0(C0), .D0(D0),
+ .A1(A1), .B1(B1), .C1(C1), .D1(D1),
+ .S0(F0), .S1(F1),
+ .COUT(FCO)
+ );
+ end else if (MODE == "RAMW") begin
+ assign WDO0 = C1;
+ assign WDO1 = A1;
+ assign WDO2 = D1;
+ assign WDO3 = B1;
+ assign WADO0 = D0;
+ assign WADO1 = B0;
+ assign WADO2 = C0;
+ assign WADO3 = A0;
+ end else if (MODE == "DPRAM") begin
+ TRELLIS_RAM16X2 #(
+ .INITVAL_0(permute_initval(LUT0_INITVAL)),
+ .INITVAL_1(permute_initval(LUT1_INITVAL)),
+ .WREMUX(WREMUX)
+ ) ram_i (
+ .DI0(WD0), .DI1(WD1),
+ .WAD0(WAD0), .WAD1(WAD1), .WAD2(WAD2), .WAD3(WAD3),
+ .WRE(WRE), .WCK(WCK),
+ .RAD0(D0), .RAD1(B0), .RAD2(C0), .RAD3(A0),
+ .DO0(F0), .DO1(F1)
+ );
+ // TODO: confirm RAD and INITVAL ordering
+ // DPRAM mode contract?
+ always @(*) begin
+ assert(A0==A1);
+ assert(B0==B1);
+ assert(C0==C1);
+ assert(D0==D1);
+ end
+ end else begin
+ ERROR_UNKNOWN_SLICE_MODE error();
+ end
+ endgenerate
+
+ // FF input selection muxes
+ wire muxdi0 = (REG0_SD == "1") ? DI0 : M0;
+ wire muxdi1 = (REG1_SD == "1") ? DI1 : M1;
+ // Flipflops
+ TRELLIS_FF #(
+ .GSR(GSR),
+ .CEMUX(CEMUX),
+ .CLKMUX(CLKMUX),
+ .LSRMUX(LSRMUX),
+ .SRMODE(SRMODE),
+ .REGSET(REG0_REGSET)
+ ) ff_0 (
+ .CLK(CLK), .LSR(LSR), .CE(CE),
+ .DI(muxdi0),
+ .Q(Q0)
+ );
+ TRELLIS_FF #(
+ .GSR(GSR),
+ .CEMUX(CEMUX),
+ .CLKMUX(CLKMUX),
+ .LSRMUX(LSRMUX),
+ .SRMODE(SRMODE),
+ .REGSET(REG1_REGSET)
+ ) ff_1 (
+ .CLK(CLK), .LSR(LSR), .CE(CE),
+ .DI(muxdi1),
+ .Q(Q1)
+ );
+endmodule
+
diff --git a/techlibs/ecp5/dram.txt b/techlibs/ecp5/dram.txt
new file mode 100644
index 000000000..b3252fa9a
--- /dev/null
+++ b/techlibs/ecp5/dram.txt
@@ -0,0 +1,16 @@
+bram $__TRELLIS_DPR16X4
+ init 1
+ abits 4
+ dbits 4
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 0 1
+ transp 0 0
+ clocks 0 1
+ clkpol 0 2
+endbram
+
+match $__TRELLIS_DPR16X4
+ make_outreg
+endmatch
diff --git a/techlibs/ecp5/drams_map.v b/techlibs/ecp5/drams_map.v
new file mode 100644
index 000000000..3b3de831f
--- /dev/null
+++ b/techlibs/ecp5/drams_map.v
@@ -0,0 +1,28 @@
+module \$__TRELLIS_DPR16X4 (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
+ parameter [63:0] INIT = 64'bx;
+ parameter CLKPOL2 = 1;
+ input CLK1;
+
+ input [3:0] A1ADDR;
+ output [3:0] A1DATA;
+
+ input [3:0] B1ADDR;
+ input [3:0] B1DATA;
+ input B1EN;
+
+ localparam WCKMUX = CLKPOL2 ? "WCK" : "INV";
+
+ TRELLIS_DPR16X4 #(
+ .INITVAL(INIT),
+ .WCKMUX(WCKMUX),
+ .WREMUX("WRE")
+ ) _TECHMAP_REPLACE_ (
+ .RAD(A1ADDR),
+ .DO(A1DATA),
+
+ .WAD(B1ADDR),
+ .DI(B1DATA),
+ .WCK(CLK1),
+ .WRE(B1EN)
+ );
+endmodule
diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc
new file mode 100644
index 000000000..76051d1a2
--- /dev/null
+++ b/techlibs/ecp5/synth_ecp5.cc
@@ -0,0 +1,331 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 Clifford Wolf <dave@ds0.me>
+ *
+ * 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/register.h"
+#include "kernel/celltypes.h"
+#include "kernel/rtlil.h"
+#include "kernel/log.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct SynthEcp5Pass : public ScriptPass
+{
+ SynthEcp5Pass() : ScriptPass("synth_ecp5", "synthesis for ECP5 FPGAs") { }
+
+ virtual void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" synth_ecp5 [options]\n");
+ log("\n");
+ log("This command runs synthesis for ECP5 FPGAs.\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module\n");
+ log("\n");
+ log(" -blif <file>\n");
+ log(" write the design to the specified BLIF file. writing of an output file\n");
+ log(" is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -edif <file>\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");
+ log("\n");
+ log(" -json <file>\n");
+ log(" write the design to the specified JSON file. writing of an output file\n");
+ log(" is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -run <from_label>:<to_label>\n");
+ log(" only run the commands between the labels (see below). an empty\n");
+ 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(" -noflatten\n");
+ log(" do not flatten design before synthesis\n");
+ log("\n");
+ log(" -retime\n");
+ log(" run 'abc' with -dff option\n");
+ log("\n");
+ log(" -noccu2\n");
+ log(" do not use CCU2 cells in output netlist\n");
+ log("\n");
+ log(" -nodffe\n");
+ log(" do not use flipflops with CE in output netlist\n");
+ log("\n");
+ log(" -nobram\n");
+ log(" do not use BRAM cells in output netlist\n");
+ log("\n");
+ log(" -nodram\n");
+ log(" do not use distributed RAM cells in output netlist\n");
+ log("\n");
+ log(" -nomux\n");
+ log(" do not use PFU muxes to implement LUTs larger than LUT4s\n");
+ log("\n");
+ log(" -abc2\n");
+ log(" run two passes of 'abc' for slightly improved logic density\n");
+ log("\n");
+ log(" -vpr\n");
+ log(" generate an output netlist (and BLIF file) suitable for VPR\n");
+ log(" (this feature is experimental and incomplete)\n");
+ log("\n");
+ log("\n");
+ log("The following commands are executed by this synthesis command:\n");
+ help_script();
+ log("\n");
+ }
+
+ string top_opt, blif_file, edif_file, json_file;
+ bool noccu2, nodffe, nobram, nodram, nomux, flatten, retime, abc2, vpr;
+
+ virtual void clear_flags() YS_OVERRIDE
+ {
+ top_opt = "-auto-top";
+ blif_file = "";
+ edif_file = "";
+ json_file = "";
+ noccu2 = false;
+ nodffe = false;
+ nobram = false;
+ nodram = false;
+ nomux = false;
+ flatten = true;
+ retime = false;
+ abc2 = false;
+ vpr = false;
+ }
+
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ string run_from, run_to;
+ clear_flags();
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-top" && argidx+1 < args.size()) {
+ top_opt = "-top " + args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-blif" && argidx+1 < args.size()) {
+ blif_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-edif" && argidx+1 < args.size()) {
+ edif_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-json" && argidx+1 < args.size()) {
+ json_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-run" && argidx+1 < args.size()) {
+ size_t pos = args[argidx+1].find(':');
+ if (pos == std::string::npos)
+ break;
+ run_from = args[++argidx].substr(0, pos);
+ run_to = args[argidx].substr(pos+1);
+ continue;
+ }
+ if (args[argidx] == "-flatten") {
+ flatten = true;
+ continue;
+ }
+ if (args[argidx] == "-noflatten") {
+ flatten = false;
+ continue;
+ }
+ if (args[argidx] == "-retime") {
+ retime = true;
+ continue;
+ }
+ if (args[argidx] == "-noccu2") {
+ noccu2 = true;
+ continue;
+ }
+ if (args[argidx] == "-nodffe") {
+ nodffe = true;
+ continue;
+ }
+ if (args[argidx] == "-nobram") {
+ nobram = true;
+ continue;
+ }
+ if (args[argidx] == "-nodram") {
+ nodram = true;
+ continue;
+ }
+ if (args[argidx] == "-nomux") {
+ nomux = true;
+ continue;
+ }
+ if (args[argidx] == "-abc2") {
+ abc2 = true;
+ continue;
+ }
+ if (args[argidx] == "-vpr") {
+ vpr = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (!design->full_selection())
+ log_cmd_error("This comannd only operates on fully selected designs!\n");
+
+ log_header(design, "Executing SYNTH_ECP5 pass.\n");
+ log_push();
+
+ run_script(design, run_from, run_to);
+
+ log_pop();
+ }
+
+ virtual void script() YS_OVERRIDE
+ {
+ if (check_label("begin"))
+ {
+ run("read_verilog -lib +/ecp5/cells_sim.v");
+ run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
+ }
+
+ if (flatten && check_label("flatten", "(unless -noflatten)"))
+ {
+ run("proc");
+ run("flatten");
+ run("tribuf -logic");
+ run("deminout");
+ }
+
+ if (check_label("coarse"))
+ {
+ run("synth -run coarse");
+ }
+
+ if (!nobram && check_label("bram", "(skip if -nobram)"))
+ {
+ //TODO
+#if 0
+ run("memory_bram -rules +/ecp5/brams.txt");
+ run("techmap -map +/ecp5/brams_map.v");
+#endif
+ }
+
+ if (!nodram && check_label("dram", "(skip if -nodram)"))
+ {
+ run("memory_bram -rules +/ecp5/dram.txt");
+ run("techmap -map +/ecp5/drams_map.v");
+ }
+
+ if (check_label("fine"))
+ {
+ run("opt -fast -mux_undef -undriven -fine");
+ run("memory_map");
+ run("opt -undriven -fine");
+ if (noccu2)
+ run("techmap");
+ else
+ run("techmap -map +/techmap.v -map +/ecp5/arith_map.v");
+ if (retime || help_mode)
+ run("abc -dff", "(only if -retime)");
+ }
+
+ if (check_label("map_ffs"))
+ {
+ run("dffsr2dff");
+ run("dff2dffs");
+ run("opt_clean");
+ if (!nodffe)
+ run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*");
+ run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
+ run("opt_expr -mux_undef");
+ run("simplemap");
+ // TODO
+#if 0
+ run("ecp5_ffinit");
+#endif
+ }
+
+ if (check_label("map_luts"))
+ {
+ if (abc2 || help_mode) {
+ run("abc", " (only if -abc2)");
+ }
+ //TODO
+#if 0
+ run("techmap -map +/ecp5/latches_map.v");
+#endif
+ if (nomux)
+ run("abc -lut 4");
+ else
+ run("abc -lut 4:7");
+ run("clean");
+ }
+
+ if (check_label("map_cells"))
+ {
+ if (vpr)
+ run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
+ else
+ run("techmap -map +/ecp5/cells_map.v", "(with -D NO_LUT in vpr mode)");
+
+ run("clean");
+ }
+
+ if (check_label("check"))
+ {
+ run("hierarchy -check");
+ run("stat");
+ run("check -noinit");
+ }
+
+ if (check_label("blif"))
+ {
+ if (!blif_file.empty() || help_mode) {
+ if (vpr || help_mode) {
+ run(stringf("opt_clean -purge"),
+ " (vpr mode)");
+ run(stringf("write_blif -attr -cname -conn -param %s",
+ help_mode ? "<file-name>" : blif_file.c_str()),
+ " (vpr mode)");
+ }
+ if (!vpr)
+ run(stringf("write_blif -gates -attr -param %s",
+ help_mode ? "<file-name>" : blif_file.c_str()),
+ " (non-vpr mode)");
+ }
+ }
+
+ if (check_label("edif"))
+ {
+ if (!edif_file.empty() || help_mode)
+ run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
+ }
+
+ if (check_label("json"))
+ {
+ if (!json_file.empty() || help_mode)
+ run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
+ }
+ }
+} SynthEcp5Pass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v
index 45a02111f..9f73aeb07 100644
--- a/techlibs/ice40/cells_sim.v
+++ b/techlibs/ice40/cells_sim.v
@@ -657,7 +657,12 @@ module ICESTORM_LC (
parameter [0:0] SET_NORESET = 0;
parameter [0:0] ASYNC_SR = 0;
- assign COUT = CARRY_ENABLE ? (I1 && I2) || ((I1 || I2) && CIN) : 1'bx;
+ parameter [0:0] CIN_CONST = 0;
+ parameter [0:0] CIN_SET = 0;
+
+ wire mux_cin = CIN_CONST ? CIN_SET : CIN;
+
+ assign COUT = CARRY_ENABLE ? (I1 && I2) || ((I1 || I2) && mux_cin) : 1'bx;
wire [7:0] lut_s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0];
wire [3:0] lut_s2 = I2 ? lut_s3[ 7:4] : lut_s3[3:0];
@@ -1226,4 +1231,3 @@ module SB_IO_OD (
endgenerate
`endif
endmodule
-
diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc
index ae72f5d64..7af60f297 100644
--- a/techlibs/ice40/ice40_opt.cc
+++ b/techlibs/ice40/ice40_opt.cc
@@ -26,6 +26,13 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
+static SigBit get_bit_or_zero(const SigSpec &sig)
+{
+ if (GetSize(sig) == 0)
+ return State::S0;
+ return sig[0];
+}
+
static void run_ice40_opts(Module *module, bool unlut_mode)
{
pool<SigBit> optimized_co;
@@ -45,7 +52,11 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
SigSpec non_const_inputs, replacement_output;
int count_zeros = 0, count_ones = 0;
- SigBit inbit[3] = {cell->getPort("\\I0"), cell->getPort("\\I1"), cell->getPort("\\CI")};
+ SigBit inbit[3] = {
+ get_bit_or_zero(cell->getPort("\\I0")),
+ get_bit_or_zero(cell->getPort("\\I1")),
+ get_bit_or_zero(cell->getPort("\\CI"))
+ };
for (int i = 0; i < 3; i++)
if (inbit[i].wire == nullptr) {
if (inbit[i] == State::S1)
@@ -63,8 +74,8 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
replacement_output = non_const_inputs;
if (GetSize(replacement_output)) {
- optimized_co.insert(sigmap(cell->getPort("\\CO")));
- module->connect(cell->getPort("\\CO"), replacement_output);
+ optimized_co.insert(sigmap(cell->getPort("\\CO")[0]));
+ module->connect(cell->getPort("\\CO")[0], replacement_output);
module->design->scratchpad_set_bool("opt.did_something", true);
log("Optimized away SB_CARRY cell %s.%s: CO=%s\n",
log_id(module), log_id(cell), log_signal(replacement_output));
@@ -78,10 +89,10 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
{
SigSpec inbits;
- inbits.append(cell->getPort("\\I0"));
- inbits.append(cell->getPort("\\I1"));
- inbits.append(cell->getPort("\\I2"));
- inbits.append(cell->getPort("\\I3"));
+ inbits.append(get_bit_or_zero(cell->getPort("\\I0")));
+ inbits.append(get_bit_or_zero(cell->getPort("\\I1")));
+ inbits.append(get_bit_or_zero(cell->getPort("\\I2")));
+ inbits.append(get_bit_or_zero(cell->getPort("\\I3")));
sigmap.apply(inbits);
if (unlut_mode)
@@ -104,8 +115,13 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
cell->setParam("\\LUT", cell->getParam("\\LUT_INIT"));
cell->unsetParam("\\LUT_INIT");
- cell->setPort("\\A", SigSpec({cell->getPort("\\I3"), cell->getPort("\\I2"), cell->getPort("\\I1"), cell->getPort("\\I0")}));
- cell->setPort("\\Y", cell->getPort("\\O"));
+ cell->setPort("\\A", SigSpec({
+ get_bit_or_zero(cell->getPort("\\I3")),
+ get_bit_or_zero(cell->getPort("\\I2")),
+ get_bit_or_zero(cell->getPort("\\I1")),
+ get_bit_or_zero(cell->getPort("\\I0"))
+ }));
+ cell->setPort("\\Y", cell->getPort("\\O")[0]);
cell->unsetPort("\\I0");
cell->unsetPort("\\I1");
cell->unsetPort("\\I2");
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index 177581d53..abd890a56 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -45,7 +45,11 @@ struct SynthIce40Pass : public ScriptPass
log(" is omitted if this parameter is not specified.\n");
log("\n");
log(" -edif <file>\n");
- log(" write the design to the specified edif file. writing of an output file\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");
+ log("\n");
+ log(" -json <file>\n");
+ log(" write the design to the specified JSON file. writing of an output file\n");
log(" is omitted if this parameter is not specified.\n");
log("\n");
log(" -run <from_label>:<to_label>\n");
@@ -81,7 +85,7 @@ struct SynthIce40Pass : public ScriptPass
log("\n");
}
- string top_opt, blif_file, edif_file;
+ string top_opt, blif_file, edif_file, json_file;
bool nocarry, nodffe, nobram, flatten, retime, abc2, vpr;
virtual void clear_flags() YS_OVERRIDE
@@ -89,6 +93,7 @@ struct SynthIce40Pass : public ScriptPass
top_opt = "-auto-top";
blif_file = "";
edif_file = "";
+ json_file = "";
nocarry = false;
nodffe = false;
nobram = false;
@@ -118,6 +123,10 @@ struct SynthIce40Pass : public ScriptPass
edif_file = args[++argidx];
continue;
}
+ if (args[argidx] == "-json" && argidx+1 < args.size()) {
+ json_file = args[++argidx];
+ continue;
+ }
if (args[argidx] == "-run" && argidx+1 < args.size()) {
size_t pos = args[argidx+1].find(':');
if (pos == std::string::npos)
@@ -260,17 +269,15 @@ struct SynthIce40Pass : public ScriptPass
if (!blif_file.empty() || help_mode) {
if (vpr || help_mode) {
run(stringf("opt_clean -purge"),
- " "
- " (vpr mode)");
+ " (vpr mode)");
run(stringf("write_blif -attr -cname -conn -param %s",
- help_mode ? "<file-name>" : blif_file.c_str()),
- " (vpr mode)");
+ help_mode ? "<file-name>" : blif_file.c_str()),
+ " (vpr mode)");
}
if (!vpr)
run(stringf("write_blif -gates -attr -param %s",
- help_mode ? "<file-name>" : blif_file.c_str()),
- " "
- " (non-vpr mode)");
+ help_mode ? "<file-name>" : blif_file.c_str()),
+ " (non-vpr mode)");
}
}
@@ -279,6 +286,12 @@ struct SynthIce40Pass : public ScriptPass
if (!edif_file.empty() || help_mode)
run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
}
+
+ if (check_label("json"))
+ {
+ if (!json_file.empty() || help_mode)
+ run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
+ }
}
} SynthIce40Pass;