Merge pull request #1432 from YosysHQ/eddie/fix1427
Refactor peepopt_dffmux and be sensitive to \init when trimming
diff --git a/CHANGELOG b/CHANGELOG
index c1ffaa4..1fc139d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -50,6 +50,7 @@
- "synth_ecp5" to now infer DSP blocks (-nodsp to disable, experimental)
- "synth_ice40 -dsp" to infer DSP blocks
- Added latch support to synth_xilinx
+ - Added "check -mapped"
Yosys 0.8 .. Yosys 0.9
----------------------
diff --git a/Makefile b/Makefile
index 2644721..33c04cf 100644
--- a/Makefile
+++ b/Makefile
@@ -115,7 +115,7 @@
LDLIBS += -lrt
endif
-YOSYS_VER := 0.9+899
+YOSYS_VER := 0.9+932
GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
OBJS = kernel/version_$(GIT_REV).o
@@ -128,7 +128,7 @@
# 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 = 5776ad0
+ABCREV = 623b5e8
ABCPULL = 1
ABCURL ?= https://github.com/berkeley-abc/abc
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1
diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc
index 4018cc9..46890b0 100644
--- a/backends/aiger/xaiger.cc
+++ b/backends/aiger/xaiger.cc
@@ -203,7 +203,7 @@
// box ordering, but not individual AIG cells
dict<SigBit, pool<IdString>> bit_drivers, bit_users;
TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
- bool abc_box_seen = false;
+ bool abc9_box_seen = false;
for (auto cell : module->selected_cells()) {
if (cell->type == "$_NOT_")
@@ -242,8 +242,8 @@
log_assert(!holes_mode);
RTLIL::Module* inst_module = module->design->module(cell->type);
- if (inst_module && inst_module->attributes.count("\\abc_box_id")) {
- abc_box_seen = true;
+ if (inst_module && inst_module->attributes.count("\\abc9_box_id")) {
+ abc9_box_seen = true;
if (!holes_mode) {
toposort.node(cell->name);
@@ -291,10 +291,10 @@
if (is_output) {
int arrival = 0;
if (port_wire) {
- auto it = port_wire->attributes.find("\\abc_arrival");
+ auto it = port_wire->attributes.find("\\abc9_arrival");
if (it != port_wire->attributes.end()) {
if (it->second.flags != 0)
- log_error("Attribute 'abc_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type));
+ log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type));
arrival = it->second.as_int();
}
}
@@ -318,7 +318,7 @@
//log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
}
- if (abc_box_seen) {
+ if (abc9_box_seen) {
for (auto &it : bit_users)
if (bit_drivers.count(it.first))
for (auto driver_cell : bit_drivers.at(it.first))
@@ -347,7 +347,7 @@
log_assert(cell);
RTLIL::Module* box_module = module->design->module(cell->type);
- if (!box_module || !box_module->attributes.count("\\abc_box_id"))
+ if (!box_module || !box_module->attributes.count("\\abc9_box_id"))
continue;
bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */);
@@ -398,7 +398,7 @@
else {
Wire *wire = module->addWire(NEW_ID, GetSize(w));
if (blackbox)
- wire->set_bool_attribute(ID(abc_padding));
+ wire->set_bool_attribute(ID(abc9_padding));
rhs = wire;
cell->setPort(port_name, rhs);
}
@@ -666,7 +666,7 @@
write_h_buffer(box_inputs);
write_h_buffer(box_outputs);
- write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int());
+ write_h_buffer(box_module->attributes.at("\\abc9_box_id").as_int());
write_h_buffer(box_count++);
}
diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py
index 445a42e..3d6d3e1 100644
--- a/backends/smt2/smtbmc.py
+++ b/backends/smt2/smtbmc.py
@@ -1256,7 +1256,7 @@
return smt.check_sat()
if tempind:
- retstatus = False
+ retstatus = "FAILED"
skip_counter = step_size
for step in range(num_steps, -1, -1):
if smt.forall:
@@ -1303,7 +1303,7 @@
else:
print_msg("Temporal induction successful.")
- retstatus = True
+ retstatus = "PASSED"
break
elif covermode:
@@ -1321,7 +1321,7 @@
smt.write("(define-fun covers_0 ((state |%s_s|)) (_ BitVec %d) %s)" % (topmod, len(cover_desc), cover_expr))
step = 0
- retstatus = False
+ retstatus = "FAILED"
found_failed_assert = False
assert step_size == 1
@@ -1365,7 +1365,7 @@
if smt_check_sat() == "unsat":
print("%s Cannot appended steps without violating assumptions!" % smt.timestamp())
found_failed_assert = True
- retstatus = False
+ retstatus = "FAILED"
break
reached_covers = smt.bv2bin(smt.get("(covers_%d s%d)" % (coveridx, step)))
@@ -1400,7 +1400,7 @@
break
if "1" not in cover_mask:
- retstatus = True
+ retstatus = "PASSED"
break
step += 1
@@ -1412,7 +1412,7 @@
else: # not tempind, covermode
step = 0
- retstatus = True
+ retstatus = "PASSED"
while step < num_steps:
smt_state(step)
smt_assert_consequent("(|%s_u| s%d)" % (topmod, step))
@@ -1459,8 +1459,8 @@
print_msg("Checking assumptions in steps %d to %d.." % (step, last_check_step))
if smt_check_sat() == "unsat":
- print("%s Warmup failed!" % smt.timestamp())
- retstatus = False
+ print("%s Assumptions are unsatisfiable!" % smt.timestamp())
+ retstatus = "PREUNSAT"
break
if not final_only:
@@ -1487,13 +1487,13 @@
print_msg("Re-solving with appended steps..")
if smt_check_sat() == "unsat":
print("%s Cannot appended steps without violating assumptions!" % smt.timestamp())
- retstatus = False
+ retstatus = "FAILED"
break
print_anyconsts(step)
for i in range(step, last_check_step+1):
print_failed_asserts(i)
write_trace(0, last_check_step+1+append_steps, '%')
- retstatus = False
+ retstatus = "FAILED"
break
smt_pop()
@@ -1519,7 +1519,7 @@
print_anyconsts(i)
print_failed_asserts(i, final=True)
write_trace(0, i+1, '%')
- retstatus = False
+ retstatus = "FAILED"
break
smt_pop()
@@ -1534,7 +1534,7 @@
print_msg("Solving for step %d.." % (last_check_step))
if smt_check_sat() != "sat":
print("%s No solution found!" % smt.timestamp())
- retstatus = False
+ retstatus = "FAILED"
break
elif dumpall:
@@ -1551,5 +1551,5 @@
smt.write("(exit)")
smt.wait()
-print_msg("Status: %s" % ("PASSED" if retstatus else "FAILED (!)"))
-sys.exit(0 if retstatus else 1)
+print_msg("Status: %s" % retstatus)
+sys.exit(0 if retstatus == "PASSED" else 1)
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc
index 5a1da4d..cf06019 100644
--- a/frontends/aiger/aigerparse.cc
+++ b/frontends/aiger/aigerparse.cc
@@ -740,22 +740,22 @@
log_assert(box_module);
if (seen_boxes.insert(cell->type).second) {
- auto it = box_module->attributes.find("\\abc_carry");
+ auto it = box_module->attributes.find("\\abc9_carry");
if (it != box_module->attributes.end()) {
RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr;
auto carry_in_out = it->second.decode_string();
auto pos = carry_in_out.find(',');
if (pos == std::string::npos)
- log_error("'abc_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type));
+ log_error("'abc9_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type));
auto carry_in_name = RTLIL::escape_id(carry_in_out.substr(0, pos));
carry_in = box_module->wire(carry_in_name);
if (!carry_in || !carry_in->port_input)
- log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str());
+ log_error("'abc9_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str());
auto carry_out_name = RTLIL::escape_id(carry_in_out.substr(pos+1));
carry_out = box_module->wire(carry_out_name);
if (!carry_out || !carry_out->port_output)
- log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str());
+ log_error("'abc9_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str());
auto &ports = box_module->ports;
for (auto jt = ports.begin(); jt != ports.end(); ) {
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 21279cb..37a69d8 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -1382,10 +1382,10 @@
// create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces
// This method is used to explode the interface when the interface is a port of the module (not instantiated inside)
-RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail)
+RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool /*mayfail*/)
{
AstNode *new_ast = NULL;
- std::string modname = derive_common(design, parameters, &new_ast, mayfail);
+ std::string modname = derive_common(design, parameters, &new_ast);
// Since interfaces themselves may be instantiated with different parameters,
// "modname" must also take those into account, so that unique modules
@@ -1398,11 +1398,17 @@
has_interfaces = true;
}
+ std::string new_modname = modname;
if (has_interfaces)
- modname += "$interfaces$" + interf_info;
+ new_modname += "$interfaces$" + interf_info;
- if (!design->has(modname)) {
+ if (!design->has(new_modname)) {
+ if (!new_ast) {
+ auto mod = dynamic_cast<AstModule*>(design->module(modname));
+ new_ast = mod->ast->clone();
+ }
+ modname = new_modname;
new_ast->str = modname;
// Iterate over all interfaces which are ports in this module:
@@ -1455,10 +1461,10 @@
}
// create a new parametric module (when needed) and return the name of the generated module - without support for interfaces
-RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail)
+RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool /*mayfail*/)
{
AstNode *new_ast = NULL;
- std::string modname = derive_common(design, parameters, &new_ast, mayfail);
+ std::string modname = derive_common(design, parameters, &new_ast);
if (!design->has(modname)) {
new_ast->str = modname;
@@ -1473,47 +1479,75 @@
}
// create a new parametric module (when needed) and return the name of the generated module
-std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool)
+std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out)
{
std::string stripped_name = name.str();
if (stripped_name.compare(0, 9, "$abstract") == 0)
stripped_name = stripped_name.substr(9);
- log_header(design, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name.c_str());
- loadconfig();
-
std::string para_info;
- AstNode *new_ast = ast->clone();
int para_counter = 0;
- int orig_parameters_n = parameters.size();
- for (auto it = new_ast->children.begin(); it != new_ast->children.end(); it++) {
- AstNode *child = *it;
+ for (const auto child : ast->children) {
if (child->type != AST_PARAMETER)
continue;
para_counter++;
std::string para_id = child->str;
if (parameters.count(para_id) > 0) {
log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str])));
- rewrite_parameter:
para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
- delete child->children.at(0);
- if ((parameters[para_id].flags & RTLIL::CONST_FLAG_REAL) != 0) {
- child->children[0] = new AstNode(AST_REALVALUE);
- child->children[0]->realvalue = std::stod(parameters[para_id].decode_string());
- } else if ((parameters[para_id].flags & RTLIL::CONST_FLAG_STRING) != 0)
- child->children[0] = AstNode::mkconst_str(parameters[para_id].decode_string());
- else
- child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, (parameters[para_id].flags & RTLIL::CONST_FLAG_SIGNED) != 0);
- parameters.erase(para_id);
continue;
}
para_id = stringf("$%d", para_counter);
if (parameters.count(para_id) > 0) {
log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
+ para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
+ continue;
+ }
+ }
+
+ std::string modname;
+ if (parameters.size() == 0)
+ modname = stripped_name;
+ else if (para_info.size() > 60)
+ modname = "$paramod$" + sha1(para_info) + stripped_name;
+ else
+ modname = "$paramod" + stripped_name + para_info;
+
+ if (design->has(modname))
+ return modname;
+
+ log_header(design, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name.c_str());
+ loadconfig();
+
+ AstNode *new_ast = ast->clone();
+ para_counter = 0;
+ for (auto child : new_ast->children) {
+ if (child->type != AST_PARAMETER)
+ continue;
+ para_counter++;
+ std::string para_id = child->str;
+ if (parameters.count(para_id) > 0) {
+ log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str])));
+ goto rewrite_parameter;
+ }
+ para_id = stringf("$%d", para_counter);
+ if (parameters.count(para_id) > 0) {
+ log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
goto rewrite_parameter;
}
+ continue;
+ rewrite_parameter:
+ delete child->children.at(0);
+ if ((parameters[para_id].flags & RTLIL::CONST_FLAG_REAL) != 0) {
+ child->children[0] = new AstNode(AST_REALVALUE);
+ child->children[0]->realvalue = std::stod(parameters[para_id].decode_string());
+ } else if ((parameters[para_id].flags & RTLIL::CONST_FLAG_STRING) != 0)
+ child->children[0] = AstNode::mkconst_str(parameters[para_id].decode_string());
+ else
+ child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, (parameters[para_id].flags & RTLIL::CONST_FLAG_SIGNED) != 0);
+ parameters.erase(para_id);
}
for (auto param : parameters) {
@@ -1526,16 +1560,6 @@
new_ast->children.push_back(defparam);
}
- std::string modname;
-
- if (orig_parameters_n == 0)
- modname = stripped_name;
- else if (para_info.size() > 60)
- modname = "$paramod$" + sha1(para_info) + stripped_name;
- else
- modname = "$paramod" + stripped_name + para_info;
-
-
(*new_ast_out) = new_ast;
return modname;
}
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index 93fee91..0ec249a 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -296,7 +296,7 @@
~AstModule() YS_OVERRIDE;
RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE;
RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE;
- std::string derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool mayfail);
+ std::string derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out);
void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces) YS_OVERRIDE;
RTLIL::Module *clone() const YS_OVERRIDE;
void loadconfig() const;
diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc
index 83e1353..add17c2 100644
--- a/frontends/rpc/rpc_frontend.cc
+++ b/frontends/rpc/rpc_frontend.cc
@@ -28,14 +28,13 @@
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/un.h>
+extern char **environ;
#endif
#include "libs/json11/json11.hpp"
#include "libs/sha1/sha1.h"
#include "kernel/yosys.h"
-extern char **environ;
-
YOSYS_NAMESPACE_BEGIN
#if defined(_WIN32)
@@ -238,6 +237,11 @@
#if defined(_WIN32)
+#if defined(_MSC_VER)
+#include <BaseTsd.h>
+typedef SSIZE_T ssize_t;
+#endif
+
struct HandleRpcServer : RpcServer {
HANDLE hsend, hrecv;
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index ded1cd6..bd2fd91 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -3554,6 +3554,12 @@
if (width_ != other.width_)
return false;
+ // Without this, SigSpec() == SigSpec(State::S0, 0) will fail
+ // since the RHS will contain one SigChunk of width 0 causing
+ // the size check below to fail
+ if (width_ == 0)
+ return true;
+
pack();
other.pack();
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index c08653b..e5b24cc 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -609,8 +609,11 @@
std::string decode_string() const;
inline int size() const { return bits.size(); }
+ inline bool empty() const { return bits.empty(); }
inline RTLIL::State &operator[](int index) { return bits.at(index); }
inline const RTLIL::State &operator[](int index) const { return bits.at(index); }
+ inline decltype(bits)::iterator begin() { return bits.begin(); }
+ inline decltype(bits)::iterator end() { return bits.end(); }
bool is_fully_zero() const;
bool is_fully_ones() const;
diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc
index 64697c1..820ecac 100644
--- a/passes/cmds/check.cc
+++ b/passes/cmds/check.cc
@@ -41,14 +41,24 @@
log("\n");
log(" - used wires that do not have a driver\n");
log("\n");
- log("When called with -noinit then this command also checks for wires which have\n");
- log("the 'init' attribute set.\n");
+ log("Options:\n");
log("\n");
- log("When called with -initdrv then this command also checks for wires which have\n");
- log("the 'init' attribute set and aren't driven by a FF cell type.\n");
+ log(" -noinit\n");
+ log(" Also check for wires which have the 'init' attribute set.\n");
log("\n");
- log("When called with -assert then the command will produce an error if any\n");
- log("problems are found in the current design.\n");
+ log(" -initdrv\n");
+ log(" Also check for wires that have the 'init' attribute set and are not\n");
+ log(" driven by an FF cell type.\n");
+ log("\n");
+ log(" -mapped\n");
+ log(" Also check for internal cells that have not been mapped to cells of the\n");
+ log(" target architecture.\n");
+ log("\n");
+ log(" -allow-tbuf\n");
+ log(" Modify the -mapped behavior to still allow $_TBUF_ cells.\n");
+ log("\n");
+ log(" -assert\n");
+ log(" Produce a runtime error if any problems are found in the current design.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -56,6 +66,8 @@
int counter = 0;
bool noinit = false;
bool initdrv = false;
+ bool mapped = false;
+ bool allow_tbuf = false;
bool assert_mode = false;
size_t argidx;
@@ -68,6 +80,14 @@
initdrv = true;
continue;
}
+ if (args[argidx] == "-mapped") {
+ mapped = true;
+ continue;
+ }
+ if (args[argidx] == "-allow-tbuf") {
+ allow_tbuf = true;
+ continue;
+ }
if (args[argidx] == "-assert") {
assert_mode = true;
continue;
@@ -135,29 +155,37 @@
TopoSort<string> topo;
for (auto cell : module->cells())
- for (auto &conn : cell->connections()) {
- SigSpec sig = sigmap(conn.second);
- bool logic_cell = yosys_celltypes.cell_evaluable(cell->type);
- if (cell->input(conn.first))
- for (auto bit : sig)
- if (bit.wire) {
+ {
+ if (mapped && cell->type.begins_with("$") && design->module(cell->type) == nullptr) {
+ if (allow_tbuf && cell->type == ID($_TBUF_)) goto cell_allowed;
+ log_warning("Cell %s.%s is an unmapped internal cell of type %s.\n", log_id(module), log_id(cell), log_id(cell->type));
+ counter++;
+ cell_allowed:;
+ }
+ for (auto &conn : cell->connections()) {
+ SigSpec sig = sigmap(conn.second);
+ bool logic_cell = yosys_celltypes.cell_evaluable(cell->type);
+ if (cell->input(conn.first))
+ for (auto bit : sig)
+ if (bit.wire) {
+ if (logic_cell)
+ topo.edge(stringf("wire %s", log_signal(bit)),
+ stringf("cell %s (%s)", log_id(cell), log_id(cell->type)));
+ used_wires.insert(bit);
+ }
+ if (cell->output(conn.first))
+ for (int i = 0; i < GetSize(sig); i++) {
if (logic_cell)
- topo.edge(stringf("wire %s", log_signal(bit)),
- stringf("cell %s (%s)", log_id(cell), log_id(cell->type)));
- used_wires.insert(bit);
+ topo.edge(stringf("cell %s (%s)", log_id(cell), log_id(cell->type)),
+ stringf("wire %s", log_signal(sig[i])));
+ if (sig[i].wire)
+ wire_drivers[sig[i]].push_back(stringf("port %s[%d] of cell %s (%s)",
+ log_id(conn.first), i, log_id(cell), log_id(cell->type)));
}
- if (cell->output(conn.first))
- for (int i = 0; i < GetSize(sig); i++) {
- if (logic_cell)
- topo.edge(stringf("cell %s (%s)", log_id(cell), log_id(cell->type)),
- stringf("wire %s", log_signal(sig[i])));
- if (sig[i].wire)
- wire_drivers[sig[i]].push_back(stringf("port %s[%d] of cell %s (%s)",
- log_id(conn.first), i, log_id(cell), log_id(cell->type)));
- }
- if (!cell->input(conn.first) && cell->output(conn.first))
- for (auto bit : sig)
- if (bit.wire) wire_drivers_count[bit]++;
+ if (!cell->input(conn.first) && cell->output(conn.first))
+ for (auto bit : sig)
+ if (bit.wire) wire_drivers_count[bit]++;
+ }
}
pool<SigBit> init_bits;
diff --git a/passes/equiv/equiv_opt.cc b/passes/equiv/equiv_opt.cc
index 4ab5b1a..c7e6d71 100644
--- a/passes/equiv/equiv_opt.cc
+++ b/passes/equiv/equiv_opt.cc
@@ -33,7 +33,7 @@
log(" equiv_opt [options] [command]\n");
log("\n");
log("This command uses temporal induction to check circuit equivalence before and\n");
- log("after an optimization pass.\n");
+ log("after an optimization pass.\n");
log("\n");
log(" -run <from_label>:<to_label>\n");
log(" only run the commands between the labels (see below). an empty\n");
@@ -50,6 +50,9 @@
log(" -multiclock\n");
log(" run clk2fflogic before equivalence checking.\n");
log("\n");
+ log(" -async2sync\n");
+ log(" run async2sync before equivalence checking.\n");
+ log("\n");
log(" -undef\n");
log(" enable modelling of undef states during equiv_induct.\n");
log("\n");
@@ -59,7 +62,7 @@
}
std::string command, techmap_opts;
- bool assert, undef, multiclock;
+ bool assert, undef, multiclock, async2sync;
void clear_flags() YS_OVERRIDE
{
@@ -68,6 +71,7 @@
assert = false;
undef = false;
multiclock = false;
+ async2sync = false;
}
void execute(std::vector < std::string > args, RTLIL::Design * design) YS_OVERRIDE
@@ -101,6 +105,10 @@
multiclock = true;
continue;
}
+ if (args[argidx] == "-async2sync") {
+ async2sync = true;
+ continue;
+ }
break;
}
@@ -120,6 +128,9 @@
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
+ if (async2sync && multiclock)
+ log_cmd_error("The '-async2sync' and '-multiclock' options are mutually exclusive!\n");
+
log_header(design, "Executing EQUIV_OPT pass.\n");
log_push();
@@ -157,8 +168,8 @@
if (check_label("prove")) {
if (multiclock || help_mode)
run("clk2fflogic", "(only with -multiclock)");
- if (!multiclock || help_mode)
- run("async2sync", "(only without -multiclock)");
+ if (async2sync || help_mode)
+ run("async2sync", " (only with -async2sync)");
run("equiv_make gold gate equiv");
if (help_mode)
run("equiv_induct [-undef] equiv");
diff --git a/passes/pmgen/README.md b/passes/pmgen/README.md
index 2f5b8d0..3956083 100644
--- a/passes/pmgen/README.md
+++ b/passes/pmgen/README.md
@@ -190,7 +190,7 @@
select pmux->type == $pmux
slice idx GetSize(port(pmux, \S))
index <SigBit> port(pmux, \S)[idx] === port(eq, \Y)
- set pmux_slice idx
+ set pmux_slice idx
endmatch
The first argument to `slice` is the local variable name used to identify the
diff --git a/passes/pmgen/ice40_wrapcarry.pmg b/passes/pmgen/ice40_wrapcarry.pmg
index 9e64c74..bb59edb 100644
--- a/passes/pmgen/ice40_wrapcarry.pmg
+++ b/passes/pmgen/ice40_wrapcarry.pmg
@@ -9,3 +9,7 @@
index <SigSpec> port(lut, \I1) === port(carry, \I0)
index <SigSpec> port(lut, \I2) === port(carry, \I1)
endmatch
+
+code
+ accept;
+endcode
diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc
index 11c7e5e..054e123 100644
--- a/passes/pmgen/xilinx_dsp.cc
+++ b/passes/pmgen/xilinx_dsp.cc
@@ -20,6 +20,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include <deque>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -608,8 +609,13 @@
extra_args(args, argidx, design);
for (auto module : design->selected_modules()) {
+ // Experimental feature: pack $add/$sub cells with
+ // (* use_dsp48="simd" *) into DSP48E1's using its
+ // SIMD feature
xilinx_simd_pack(module, module->selected_cells());
+ // Match for all features ([ABDMP][12]?REG, pre-adder,
+ // post-adder, pattern detector, etc.) except for CREG
{
xilinx_dsp_pm pm(module, module->selected_cells());
pm.run_xilinx_dsp_pack(xilinx_dsp_pack);
@@ -618,14 +624,17 @@
// is no guarantee that the cell ordering corresponds
// to the "expected" case (i.e. the order in which
// they appear in the source) thus the possiblity
- // existed that a register got packed as CREG into a
+ // existed that a register got packed as a CREG into a
// downstream DSP that should have otherwise been a
- // PREG of an upstream DSP that had not been pattern
- // matched yet
+ // PREG of an upstream DSP that had not been visited
+ // yet
{
xilinx_dsp_CREG_pm pm(module, module->selected_cells());
pm.run_xilinx_dsp_packC(xilinx_dsp_packC);
}
+ // Lastly, identify and utilise PCOUT -> PCIN,
+ // ACOUT -> ACIN, and BCOUT-> BCIN dedicated cascade
+ // chains
{
xilinx_dsp_cascade_pm pm(module, module->selected_cells());
pm.run_xilinx_dsp_cascade();
diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg
index 3d0b1f2..604aa22 100644
--- a/passes/pmgen/xilinx_dsp.pmg
+++ b/passes/pmgen/xilinx_dsp.pmg
@@ -1,3 +1,57 @@
+// This file describes the main pattern matcher setup (of three total) that
+// forms the `xilinx_dsp` pass described in xilinx_dsp.cc
+// At a high level, it works as follows:
+// ( 1) Starting from a DSP48E1 cell
+// ( 2) Match the driver of the 'A' input to a possible $dff cell (ADREG)
+// (attached to at most two $mux cells that implement clock-enable or
+// reset functionality, using a subpattern discussed below)
+// If ADREG matched, treat 'A' input as input of ADREG
+// ( 3) Match the driver of the 'A' and 'D' inputs for a possible $add cell
+// (pre-adder)
+// ( 4) If pre-adder was present, find match 'A' input for A2REG
+// If pre-adder was not present, move ADREG to A2REG
+// If A2REG, then match 'A' input for A1REG
+// ( 5) Match 'B' input for B2REG
+// If B2REG, then match 'B' input for B1REG
+// ( 6) Match 'D' input for DREG
+// ( 7) Match 'P' output that exclusively drives an MREG
+// ( 8) Match 'P' output that exclusively drives one of two inputs to an $add
+// cell (post-adder).
+// The other input to the adder is assumed to come in from the 'C' input
+// (note: 'P' -> 'C' connections that exist for accumulators are
+// recognised in xilinx_dsp.cc).
+// ( 9) Match 'P' output that exclusively drives a PREG
+// (10) If post-adder and PREG both present, match for a $mux cell driving
+// the 'C' input, where one of the $mux's inputs is the PREG output.
+// This indicates an accumulator situation, and one where a $mux exists
+// to override the accumulated value:
+// +--------------------------------+
+// | ____ |
+// +--| \ |
+// |$mux|-+ |
+// 'C' ---|____/ | |
+// | /-------\ +----+ |
+// +----+ +-| post- |___|PREG|---+ 'P'
+// |MREG|------ | adder | +----+
+// +----+ \-------/
+// (11) If PREG present, match for a greater-than-or-equal $ge cell attached
+// to the 'P' output where it is compared to a constant that is a
+// power-of-2: e.g. `assign overflow = (PREG >= 2**40);`
+// In this scenario, the pattern detector functionality of a DSP48E1 can
+// to implement this function
+// Notes:
+// - The intention of this pattern matcher is for it to be compatible with
+// DSP48E1 cells inferred from multiply operations by Yosys, as well as for
+// user instantiations that may already contain the cells being packed...
+// (though the latter is currently untested)
+// - Since the $dff-with-optional-clock-enable-or-reset-mux pattern is used
+// for each *REG match, it has been factored out into two subpatterns:
+// in_dffe and out_dffe located at the bottom of this file.
+// - Matching for pattern detector features is currently incomplete. For
+// example, matching for underflow as well as overflow detection is
+// possible, as would auto-reset, enabling saturated arithmetic, detecting
+// custom patterns, etc.
+
pattern xilinx_dsp_pack
state <SigBit> clock
@@ -5,12 +59,11 @@
state <IdString> postAddAB postAddMuxAB
state <bool> ffA1cepol ffA2cepol ffADcepol ffB1cepol ffB2cepol ffDcepol ffMcepol ffPcepol
state <bool> ffArstpol ffADrstpol ffBrstpol ffDrstpol ffMrstpol ffPrstpol
-
state <Cell*> ffAD ffADcemux ffADrstmux ffA1 ffA1cemux ffA1rstmux ffA2 ffA2cemux ffA2rstmux
state <Cell*> ffB1 ffB1cemux ffB1rstmux ffB2 ffB2cemux ffB2rstmux
state <Cell*> ffD ffDcemux ffDrstmux ffM ffMcemux ffMrstmux ffP ffPcemux ffPrstmux
-// subpattern
+// Variables used for subpatterns
state <SigSpec> argQ argD
state <bool> ffcepol ffrstpol
state <int> ffoffset
@@ -19,6 +72,7 @@
udata <Cell*> dff dffcemux dffrstmux
udata <bool> dffcepol dffrstpol
+// (1) Starting from a DSP48E1 cell
match dsp
select dsp->type.in(\DSP48E1)
endmatch
@@ -50,17 +104,21 @@
sigM.append(P[i]);
}
log_assert(nusers(P.extract_end(i)) <= 1);
+ // This sigM could have no users if downstream sinks (e.g. $add) is
+ // narrower than $mul result, for example
+ if (sigM.empty())
+ reject;
}
else
sigM = P;
- // This sigM could have no users if downstream $add
- // is narrower than $mul result, for example
- if (sigM.empty())
- reject;
clock = port(dsp, \CLK, SigBit());
endcode
+// (2) Match the driver of the 'A' input to a possible $dff cell (ADREG)
+// (attached to at most two $mux cells that implement clock-enable or
+// reset functionality, using a subpattern discussed above)
+// If matched, treat 'A' input as input of ADREG
code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock
if (param(dsp, \ADREG).as_int() == 0) {
argQ = sigA;
@@ -81,6 +139,8 @@
}
endcode
+// (3) Match the driver of the 'A' and 'D' inputs for a possible $add cell
+// (pre-adder)
match preAdd
if sigD.empty() || sigD.is_fully_zero()
// Ensure that preAdder not already used
@@ -106,11 +166,12 @@
if (preAdd) {
sigA = port(preAdd, \A);
sigD = port(preAdd, \B);
- if (GetSize(sigA) < GetSize(sigD))
- std::swap(sigA, sigD);
}
endcode
+// (4) If pre-adder was present, find match 'A' input for A2REG
+// If pre-adder was not present, move ADREG to A2REG
+// Then match 'A' input for A1REG
code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cemux ffA2rstmux ffA2cepol ffArstpol ffA1 ffA1cemux ffA1rstmux ffA1cepol
// Only search for ffA2 if there was a pre-adder
// (otherwise ffA2 would have been matched as ffAD)
@@ -173,6 +234,8 @@
}
endcode
+// (5) Match 'B' input for B2REG
+// If B2REG, then match 'B' input for B1REG
code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol sigB clock ffB1 ffB1cemux ffB1rstmux ffB1cepol
if (param(dsp, \BREG).as_int() == 0) {
argQ = sigB;
@@ -222,6 +285,7 @@
}
endcode
+// (6) Match 'D' input for DREG
code argQ ffD ffDcemux ffDrstmux ffDcepol ffDrstpol sigD clock
if (param(dsp, \DREG).as_int() == 0) {
argQ = sigD;
@@ -242,6 +306,7 @@
}
endcode
+// (7) Match 'P' output that exclusively drives an MREG
code argD ffM ffMcemux ffMrstmux ffMcepol ffMrstpol sigM sigP clock
if (param(dsp, \MREG).as_int() == 0 && nusers(sigM) == 2) {
argD = sigM;
@@ -263,6 +328,11 @@
sigP = sigM;
endcode
+// (8) Match 'P' output that exclusively drives one of two inputs to an $add
+// cell (post-adder).
+// The other input to the adder is assumed to come in from the 'C' input
+// (note: 'P' -> 'C' connections that exist for accumulators are
+// recognised in xilinx_dsp.cc).
match postAdd
// Ensure that Z mux is not already used
if port(dsp, \OPMODE, SigSpec()).extract(4,3).is_fully_zero()
@@ -277,7 +347,9 @@
index <SigBit> port(postAdd, AB)[0] === sigP[0]
filter GetSize(port(postAdd, AB)) >= GetSize(sigP)
filter port(postAdd, AB).extract(0, GetSize(sigP)) == sigP
- filter port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(sigP[GetSize(sigP)-1], GetSize(port(postAdd, AB))-GetSize(sigP))
+ // Check that remainder of AB is a sign-extension
+ define <bool> AB_SIGNED (param(postAdd, AB == \A ? \A_SIGNED : \B_SIGNED).as_bool())
+ filter port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(AB_SIGNED ? sigP[GetSize(sigP)-1] : State::S0, GetSize(port(postAdd, AB))-GetSize(sigP))
set postAddAB AB
optional
endmatch
@@ -289,6 +361,7 @@
}
endcode
+// (9) Match 'P' output that exclusively drives a PREG
code argD ffP ffPcemux ffPrstmux ffPcepol ffPrstpol sigP clock
if (param(dsp, \PREG).as_int() == 0) {
int users = 2;
@@ -314,6 +387,19 @@
}
endcode
+// (10) If post-adder and PREG both present, match for a $mux cell driving
+// the 'C' input, where one of the $mux's inputs is the PREG output.
+// This indicates an accumulator situation, and one where a $mux exists
+// to override the accumulated value:
+// +--------------------------------+
+// | ____ |
+// +--| \ |
+// |$mux|-+ |
+// 'C' ---|____/ | |
+// | /-------\ +----+ |
+// +----+ +-| post- |___|PREG|---+ 'P'
+// |MREG|------ | adder | +----+
+// +----+ \-------/
match postAddMux
if postAdd
if ffP
@@ -331,6 +417,11 @@
sigC = port(postAddMux, postAddMuxAB == \A ? \B : \A);
endcode
+// (11) If PREG present, match for a greater-than-or-equal $ge cell attached to
+// the 'P' output where it is compared to a constant that is a power-of-2:
+// e.g. `assign overflow = (PREG >= 2**40);`
+// In this scenario, the pattern detector functionality of a DSP48E1 can
+// to implement this function
match overflow
if ffP
if param(dsp, \USE_PATTERN_DETECT, Const("NO_PATDET")).decode_string() == "NO_PATDET"
@@ -349,22 +440,45 @@
// #######################
+// Subpattern for matching against input registers, based on knowledge of the
+// 'Q' input. Typically, identifying registers with clock-enable and reset
+// capability would be a task would be handled by other Yosys passes such as
+// dff2dffe, but since DSP inference happens much before this, these patterns
+// have to be manually identified.
+// At a high level:
+// (1) Starting from a $dff cell that (partially or fully) drives the given
+// 'Q' argument
+// (2) Match for a $mux cell implementing synchronous reset semantics ---
+// one that exclusively drives the 'D' input of the $dff, with one of its
+// $mux inputs being fully zero
+// (3) Match for a $mux cell implement clock enable semantics --- one that
+// exclusively drives the 'D' input of the $dff (or the other input of
+// the reset $mux) and where one of this $mux's inputs is connected to
+// the 'Q' output of the $dff
subpattern in_dffe
arg argD argQ clock
code
dff = nullptr;
- for (auto c : argQ.chunks()) {
+ for (const auto &c : argQ.chunks()) {
+ // Abandon matches when 'Q' is a constant
if (!c.wire)
reject;
+ // Abandon matches when 'Q' has the keep attribute set
if (c.wire->get_bool_attribute(\keep))
reject;
- Const init = c.wire->attributes.at(\init, State::Sx);
- if (!init.is_fully_undef() && !init.is_fully_zero())
- reject;
+ // Abandon matches when 'Q' has a non-zero init attribute set
+ // (not supported by DSP48E1)
+ Const init = c.wire->attributes.at(\init, Const());
+ if (!init.empty())
+ for (auto b : init.extract(c.offset, c.width))
+ if (b != State::Sx && b != State::S0)
+ reject;
}
endcode
+// (1) Starting from a $dff cell that (partially or fully) drives the given
+// 'Q' argument
match ff
select ff->type.in($dff)
// DSP48E1 does not support clock inversion
@@ -377,14 +491,12 @@
filter GetSize(port(ff, \Q)) >= offset + GetSize(argQ)
filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
+ filter clock == SigBit() || port(ff, \CLK) == clock
+
set ffoffset offset
endmatch
code argQ argD
-{
- if (clock != SigBit() && port(ff, \CLK) != clock)
- reject;
-
SigSpec Q = port(ff, \Q);
dff = ff;
dffclock = port(ff, \CLK);
@@ -396,9 +508,11 @@
// has two (ff, ffrstmux) users
if (nusers(dffD) > 2)
argD = SigSpec();
-}
endcode
+// (2) Match for a $mux cell implementing synchronous reset semantics ---
+// exclusively drives the 'D' input of the $dff, with one of the $mux
+// inputs being fully zero
match ffrstmux
if !argD.empty()
select ffrstmux->type.in($mux)
@@ -430,6 +544,10 @@
dffrstmux = nullptr;
endcode
+// (3) Match for a $mux cell implement clock enable semantics --- one that
+// exclusively drives the 'D' input of the $dff (or the other input of
+// the reset $mux) and where one of this $mux's inputs is connected to
+// the 'Q' output of the $dff
match ffcemux
if !argD.empty()
select ffcemux->type.in($mux)
@@ -454,16 +572,32 @@
// #######################
+// Subpattern for matching against output registers, based on knowledge of the
+// 'D' input.
+// At a high level:
+// (1) Starting from an optional $mux cell that implements clock enable
+// semantics --- one where the given 'D' argument (partially or fully)
+// drives one of its two inputs
+// (2) Starting from, or continuing onto, another optional $mux cell that
+// implements synchronous reset semantics --- one where the given 'D'
+// argument (or the clock enable $mux output) drives one of its two inputs
+// and where the other input is fully zero
+// (3) Match for a $dff cell (whose 'D' input is the 'D' argument, or the
+// output of the previous clock enable or reset $mux cells)
subpattern out_dffe
arg argD argQ clock
code
dff = nullptr;
for (auto c : argD.chunks())
+ // Abandon matches when 'D' has the keep attribute set
if (c.wire->get_bool_attribute(\keep))
reject;
endcode
+// (1) Starting from an optional $mux cell that implements clock enable
+// semantics --- one where the given 'D' argument (partially or fully)
+// drives one of its two inputs
match ffcemux
select ffcemux->type.in($mux)
// ffcemux output must have two users: ffcemux and ff.D
@@ -502,6 +636,10 @@
}
endcode
+// (2) Starting from, or continuing onto, another optional $mux cell that
+// implements synchronous reset semantics --- one where the given 'D'
+// argument (or the clock enable $mux output) drives one of its two inputs
+// and where the other input is fully zero
match ffrstmux
select ffrstmux->type.in($mux)
// ffrstmux output must have two users: ffrstmux and ff.D
@@ -540,6 +678,8 @@
}
endcode
+// (3) Match for a $dff cell (whose 'D' input is the 'D' argument, or the
+// output of the previous clock enable or reset $mux cells)
match ff
select ff->type.in($dff)
// DSP48E1 does not support clock inversion
@@ -556,32 +696,30 @@
// Check that FF.Q is connected to CE-mux
filter !ffcemux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
+ filter clock == SigBit() || port(ff, \CLK) == clock
+
set ffoffset offset
endmatch
code argQ
- if (ff) {
- if (clock != SigBit() && port(ff, \CLK) != clock)
- reject;
-
- SigSpec D = port(ff, \D);
- SigSpec Q = port(ff, \Q);
- if (!ffcemux) {
- argQ = argD;
- argQ.replace(D, Q);
- }
-
- for (auto c : argQ.chunks()) {
- Const init = c.wire->attributes.at(\init, State::Sx);
- if (!init.is_fully_undef() && !init.is_fully_zero())
- reject;
- }
-
- dff = ff;
- dffQ = argQ;
- dffclock = port(ff, \CLK);
+ SigSpec D = port(ff, \D);
+ SigSpec Q = port(ff, \Q);
+ if (!ffcemux) {
+ argQ = argD;
+ argQ.replace(D, Q);
}
- // No enable/reset mux possible without flop
- else if (dffcemux || dffrstmux)
- reject;
+
+ // Abandon matches when 'Q' has a non-zero init attribute set
+ // (not supported by DSP48E1)
+ for (auto c : argQ.chunks()) {
+ Const init = c.wire->attributes.at(\init, Const());
+ if (!init.empty())
+ for (auto b : init.extract(c.offset, c.width))
+ if (b != State::Sx && b != State::S0)
+ reject;
+ }
+
+ dff = ff;
+ dffQ = argQ;
+ dffclock = port(ff, \CLK);
endcode
diff --git a/passes/pmgen/xilinx_dsp_CREG.pmg b/passes/pmgen/xilinx_dsp_CREG.pmg
index a31dc80..a570430 100644
--- a/passes/pmgen/xilinx_dsp_CREG.pmg
+++ b/passes/pmgen/xilinx_dsp_CREG.pmg
@@ -1,3 +1,26 @@
+// This file describes the second of three pattern matcher setups that
+// forms the `xilinx_dsp` pass described in xilinx_dsp.cc
+// At a high level, it works as follows:
+// (1) Starting from a DSP48E1 cell that (a) doesn't have a CREG already,
+// and (b) uses the 'C' port
+// (2) Match the driver of the 'C' input to a possible $dff cell (CREG)
+// (attached to at most two $mux cells that implement clock-enable or
+// reset functionality, using a subpattern discussed below)
+// Notes:
+// - Running CREG packing after xilinx_dsp_pack is necessary since there is no
+// guarantee that the cell ordering corresponds to the "expected" case (i.e.
+// the order in which they appear in the source) thus the possiblity existed
+// that a register got packed as a CREG into a downstream DSP that should
+// have otherwise been a PREG of an upstream DSP that had not been visited
+// yet
+// - The reason this is separated out from the xilinx_dsp.pmg file is
+// for efficiency --- each *.pmg file creates a class of the same basename,
+// which when constructed, creates a custom database tailored to the
+// pattern(s) contained within. Since the pattern in this file must be
+// executed after the pattern contained in xilinx_dsp.pmg, it is necessary
+// to reconstruct this database. Separating the two patterns into
+// independent files causes two smaller, more specific, databases.
+
pattern xilinx_dsp_packC
udata <std::function<SigSpec(const SigSpec&)>> unextend
@@ -6,7 +29,7 @@
state <bool> ffCcepol ffCrstpol
state <Cell*> ffC ffCcemux ffCrstmux
-// subpattern
+// Variables used for subpatterns
state <SigSpec> argQ argD
state <bool> ffcepol ffrstpol
state <int> ffoffset
@@ -15,13 +38,15 @@
udata <Cell*> dff dffcemux dffrstmux
udata <bool> dffcepol dffrstpol
+// (1) Starting from a DSP48E1 cell that (a) doesn't have a CREG already,
+// and (b) uses the 'C' port
match dsp
select dsp->type.in(\DSP48E1)
select param(dsp, \CREG, 1).as_int() == 0
select nusers(port(dsp, \C, SigSpec())) > 1
endmatch
-code argQ ffC ffCcemux ffCrstmux ffCcepol ffCrstpol sigC sigP clock
+code sigC sigP clock
unextend = [](const SigSpec &sig) {
int i;
for (i = GetSize(sig)-1; i > 0; i--)
@@ -48,11 +73,13 @@
else
sigP = P;
- if (sigC == sigP)
- reject;
-
clock = port(dsp, \CLK, SigBit());
+endcode
+// (2) Match the driver of the 'C' input to a possible $dff cell (CREG)
+// (attached to at most two $mux cells that implement clock-enable or
+// reset functionality, using the in_dffe subpattern)
+code argQ ffC ffCcemux ffCrstmux ffCcepol ffCrstpol sigC clock
argQ = sigC;
subpattern(in_dffe);
if (dff) {
@@ -77,22 +104,44 @@
// #######################
+// Subpattern for matching against input registers, based on knowledge of the
+// 'Q' input. Typically, identifying registers with clock-enable and reset
+// capability would be a task would be handled by other Yosys passes such as
+// dff2dffe, but since DSP inference happens much before this, these patterns
+// have to be manually identified.
+// At a high level:
+// (1) Starting from a $dff cell that (partially or fully) drives the given
+// 'Q' argument
+// (2) Match for a $mux cell implementing synchronous reset semantics ---
+// one that exclusively drives the 'D' input of the $dff, with one of its
+// $mux inputs being fully zero
+// (3) Match for a $mux cell implement clock enable semantics --- one that
+// exclusively drives the 'D' input of the $dff (or the other input of
+// the reset $mux) and where one of this $mux's inputs is connected to
+// the 'Q' output of the $dff
subpattern in_dffe
arg argD argQ clock
code
dff = nullptr;
- for (auto c : argQ.chunks()) {
+ for (const auto &c : argQ.chunks()) {
+ // Abandon matches when 'Q' is a constant
if (!c.wire)
reject;
+ // Abandon matches when 'Q' has the keep attribute set
if (c.wire->get_bool_attribute(\keep))
reject;
- Const init = c.wire->attributes.at(\init, State::Sx);
- if (!init.is_fully_undef() && !init.is_fully_zero())
- reject;
+ // Abandon matches when 'Q' has a non-zero init attribute set
+ // (not supported by DSP48E1)
+ Const init = c.wire->attributes.at(\init, Const());
+ for (auto b : init.extract(c.offset, c.width))
+ if (b != State::Sx && b != State::S0)
+ reject;
}
endcode
+// (1) Starting from a $dff cell that (partially or fully) drives the given
+// 'Q' argument
match ff
select ff->type.in($dff)
// DSP48E1 does not support clock inversion
@@ -105,14 +154,12 @@
filter GetSize(port(ff, \Q)) >= offset + GetSize(argQ)
filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
+ filter clock == SigBit() || port(ff, \CLK) == clock
+
set ffoffset offset
endmatch
code argQ argD
-{
- if (clock != SigBit() && port(ff, \CLK) != clock)
- reject;
-
SigSpec Q = port(ff, \Q);
dff = ff;
dffclock = port(ff, \CLK);
@@ -124,9 +171,11 @@
// has two (ff, ffrstmux) users
if (nusers(dffD) > 2)
argD = SigSpec();
-}
endcode
+// (2) Match for a $mux cell implementing synchronous reset semantics ---
+// exclusively drives the 'D' input of the $dff, with one of the $mux
+// inputs being fully zero
match ffrstmux
if !argD.empty()
select ffrstmux->type.in($mux)
@@ -158,6 +207,10 @@
dffrstmux = nullptr;
endcode
+// (3) Match for a $mux cell implement clock enable semantics --- one that
+// exclusively drives the 'D' input of the $dff (or the other input of
+// the reset $mux) and where one of this $mux's inputs is connected to
+// the 'Q' output of the $dff
match ffcemux
if !argD.empty()
select ffcemux->type.in($mux)
diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/passes/pmgen/xilinx_dsp_cascade.pmg
index 6f4ac58..7a32df2 100644
--- a/passes/pmgen/xilinx_dsp_cascade.pmg
+++ b/passes/pmgen/xilinx_dsp_cascade.pmg
@@ -1,3 +1,46 @@
+// This file describes the third of three pattern matcher setups that
+// forms the `xilinx_dsp` pass described in xilinx_dsp.cc
+// At a high level, it works as follows:
+// (1) Starting from a DSP48E1 cell that (a) has the Z multiplexer
+// (controlled by OPMODE[6:4]) set to zero and (b) doesn't already
+// use the 'PCOUT' port
+// (2.1) Match another DSP48E1 cell that (a) does not have the CREG enabled,
+// (b) has its Z multiplexer output set to the 'C' port, which is
+// driven by the 'P' output of the previous DSP cell, and (c) has its
+// 'PCIN' port unused
+// (2.2) Same as (2.1) but with the 'C' port driven by the 'P' output of the
+// previous DSP cell right-shifted by 17 bits
+// (3) For this subequent DSP48E1 match (i.e. PCOUT -> PCIN cascade exists)
+// if (a) the previous DSP48E1 uses either the A2REG or A1REG, (b) this
+// DSP48 does not use A2REG nor A1REG, (c) this DSP48E1 does not already
+// have an ACOUT -> ACIN cascade, (d) the previous DSP does not already
+// use its ACOUT port, then examine if an ACOUT -> ACIN cascade
+// opportunity exists by matching for a $dff-with-optional-clock-enable-
+// or-reset and checking that the 'D' input of this register is the same
+// as the 'A' input of the previous DSP
+// (4) Same as (3) but for BCOUT -> BCIN cascade
+// (5) Recursively go to (2.1) until no more matches possible, keeping track
+// of the longest possible chain found
+// (6) The longest chain is then divided into chunks of no more than
+// MAX_DSP_CASCADE in length (to prevent long cascades that exceed the
+// height of a DSP column) with each DSP in each chunk being rewritten
+// to use [ABP]COUT -> [ABP]CIN cascading as appropriate
+// Notes:
+// - Currently, [AB]COUT -> [AB]COUT cascades (3 or 4) are only considered
+// if a PCOUT -> PCIN cascade is (2.1 or 2.2) first identified; this need
+// not be the case --- [AB] cascades can exist independently of a P cascade
+// (though all three cascades must come from the same DSP). This situation
+// is not handled currently.
+// - In addition, [AB]COUT -> [AB]COUT cascades (3 or 4) are currently
+// conservative in that they examine the situation where (a) the previous
+// DSP has [AB]2REG or [AB]1REG enabled, (b) that the downstream DSP has no
+// registers enabled, and (c) that there exists only one additional register
+// between the upstream and downstream DSPs. This can certainly be relaxed
+// to identify situations ranging from (i) neither DSP uses any registers,
+// to (ii) upstream DSP has 2 registers, downstream DSP has 2 registers, and
+// there exists a further 2 registers between them. This remains a TODO
+// item.
+
pattern xilinx_dsp_cascade
udata <std::function<SigSpec(const SigSpec&)>> unextend
@@ -6,7 +49,7 @@
state <SigSpec> clock
state <int> AREG BREG
-// subpattern
+// Variables used for subpatterns
state <SigSpec> argQ argD
state <bool> ffcepol ffrstpol
state <int> ffoffset
@@ -19,12 +62,19 @@
#define MAX_DSP_CASCADE 20
endcode
+// (1) Starting from a DSP48E1 cell that (a) has the Z multiplexer
+// (controlled by OPMODE[6:4]) set to zero and (b) doesn't already
+// use the 'PCOUT' port
match first
select first->type.in(\DSP48E1)
select port(first, \OPMODE, Const(0, 7)).extract(4,3) == Const::from_string("000")
select nusers(port(first, \PCOUT, SigSpec())) <= 1
endmatch
+// (6) The longest chain is then divided into chunks of no more than
+// MAX_DSP_CASCADE in length (to prevent long cascades that exceed the
+// height of a DSP column) with each DSP in each chunk being rewritten
+// to use [ABP]COUT -> [ABP]CIN cascading as appropriate
code
longest_chain.clear();
chain.emplace_back(first, -1, -1, -1);
@@ -106,6 +156,10 @@
arg first
arg next
+// (2.1) Match another DSP48E1 cell that (a) does not have the CREG enabled,
+// (b) has its Z multiplexer output set to the 'C' port, which is
+// driven by the 'P' output of the previous DSP cell, and (c) has its
+// 'PCIN' port unused
match nextP
select nextP->type.in(\DSP48E1)
select !param(nextP, \CREG, State::S1).as_bool()
@@ -116,6 +170,8 @@
semioptional
endmatch
+// (2.2) Same as (2.1) but with the 'C' port driven by the 'P' output of the
+// previous DSP cell right-shifted by 17 bits
match nextP_shift17
if !nextP
select nextP_shift17->type.in(\DSP48E1)
@@ -145,6 +201,14 @@
}
endcode
+// (3) For this subequent DSP48E1 match (i.e. PCOUT -> PCIN cascade exists)
+// if (a) the previous DSP48E1 uses either the A2REG or A1REG, (b) this
+// DSP48 does not use A2REG nor A1REG, (c) this DSP48E1 does not already
+// have an ACOUT -> ACIN cascade, (d) the previous DSP does not already
+// use its ACOUT port, then examine if an ACOUT -> ACIN cascade
+// opportunity exists by matching for a $dff-with-optional-clock-enable-
+// or-reset and checking that the 'D' input of this register is the same
+// as the 'A' input of the previous DSP
code argQ clock AREG
AREG = -1;
if (next) {
@@ -152,7 +216,6 @@
if (param(prev, \AREG, 2).as_int() > 0 &&
param(next, \AREG, 2).as_int() > 0 &&
param(next, \A_INPUT, Const("DIRECT")).decode_string() == "DIRECT" &&
- port(next, \ACIN, SigSpec()).is_fully_zero() &&
nusers(port(prev, \ACOUT, SigSpec())) <= 1) {
argQ = unextend(port(next, \A));
clock = port(prev, \CLK);
@@ -174,6 +237,7 @@
}
endcode
+// (4) Same as (3) but for BCOUT -> BCIN cascade
code argQ clock BREG
BREG = -1;
if (next) {
@@ -203,13 +267,14 @@
}
endcode
+// (5) Recursively go to (2.1) until no more matches possible, recording the
+// longest possible chain
code
if (next) {
chain.emplace_back(next, nextP_shift17 ? 17 : nextP ? 0 : -1, AREG, BREG);
SigSpec sigC = unextend(port(next, \C));
- // TODO: Cannot use 'reject' since semioptional
if (nextP_shift17) {
if (GetSize(sigC)+17 <= GetSize(port(std::get<0>(chain.back()), \P)) &&
port(std::get<0>(chain.back()), \P).extract(17, GetSize(sigC)) != sigC)
@@ -232,22 +297,44 @@
// #######################
+// Subpattern for matching against input registers, based on knowledge of the
+// 'Q' input. Typically, identifying registers with clock-enable and reset
+// capability would be a task would be handled by other Yosys passes such as
+// dff2dffe, but since DSP inference happens much before this, these patterns
+// have to be manually identified.
+// At a high level:
+// (1) Starting from a $dff cell that (partially or fully) drives the given
+// 'Q' argument
+// (2) Match for a $mux cell implementing synchronous reset semantics ---
+// one that exclusively drives the 'D' input of the $dff, with one of its
+// $mux inputs being fully zero
+// (3) Match for a $mux cell implement clock enable semantics --- one that
+// exclusively drives the 'D' input of the $dff (or the other input of
+// the reset $mux) and where one of this $mux's inputs is connected to
+// the 'Q' output of the $dff
subpattern in_dffe
arg argD argQ clock
code
dff = nullptr;
- for (auto c : argQ.chunks()) {
+ for (const auto &c : argQ.chunks()) {
+ // Abandon matches when 'Q' is a constant
if (!c.wire)
reject;
+ // Abandon matches when 'Q' has the keep attribute set
if (c.wire->get_bool_attribute(\keep))
reject;
- Const init = c.wire->attributes.at(\init, State::Sx);
- if (!init.is_fully_undef() && !init.is_fully_zero())
- reject;
+ // Abandon matches when 'Q' has a non-zero init attribute set
+ // (not supported by DSP48E1)
+ Const init = c.wire->attributes.at(\init, Const());
+ for (auto b : init.extract(c.offset, c.width))
+ if (b != State::Sx && b != State::S0)
+ reject;
}
endcode
+// (1) Starting from a $dff cell that (partially or fully) drives the given
+// 'Q' argument
match ff
select ff->type.in($dff)
// DSP48E1 does not support clock inversion
@@ -260,14 +347,12 @@
filter GetSize(port(ff, \Q)) >= offset + GetSize(argQ)
filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
+ filter clock == SigBit() || port(ff, \CLK) == clock
+
set ffoffset offset
endmatch
code argQ argD
-{
- if (clock != SigBit() && port(ff, \CLK) != clock)
- reject;
-
SigSpec Q = port(ff, \Q);
dff = ff;
dffclock = port(ff, \CLK);
@@ -279,9 +364,11 @@
// has two (ff, ffrstmux) users
if (nusers(dffD) > 2)
argD = SigSpec();
-}
endcode
+// (2) Match for a $mux cell implementing synchronous reset semantics ---
+// exclusively drives the 'D' input of the $dff, with one of the $mux
+// inputs being fully zero
match ffrstmux
if !argD.empty()
select ffrstmux->type.in($mux)
@@ -313,6 +400,10 @@
dffrstmux = nullptr;
endcode
+// (3) Match for a $mux cell implement clock enable semantics --- one that
+// exclusively drives the 'D' input of the $dff (or the other input of
+// the reset $mux) and where one of this $mux's inputs is connected to
+// the 'Q' output of the $dff
match ffcemux
if !argD.empty()
select ffcemux->type.in($mux)
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index 09d6e96..27106cc 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -71,21 +71,21 @@
bool clk_polarity, en_polarity;
RTLIL::SigSpec clk_sig, en_sig;
-inline std::string remap_name(RTLIL::IdString abc_name)
+inline std::string remap_name(RTLIL::IdString abc9_name)
{
- return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1);
+ return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1);
}
void handle_loops(RTLIL::Design *design)
{
- Pass::call(design, "scc -set_attr abc_scc_id {}");
+ Pass::call(design, "scc -set_attr abc9_scc_id {}");
// For every unique SCC found, (arbitrarily) find the first
// cell in the component, and select (and mark) all its output
// wires
pool<RTLIL::Const> ids_seen;
for (auto cell : module->cells()) {
- auto it = cell->attributes.find(ID(abc_scc_id));
+ auto it = cell->attributes.find(ID(abc9_scc_id));
if (it != cell->attributes.end()) {
auto r = ids_seen.insert(it->second);
if (r.second) {
@@ -105,7 +105,7 @@
log_assert(w->port_input);
log_assert(b.offset < GetSize(w));
}
- w->set_bool_attribute(ID(abc_scc_break));
+ w->set_bool_attribute(ID(abc9_scc_break));
module->swap_names(b.wire, w);
c.second = RTLIL::SigBit(w, b.offset);
}
@@ -118,7 +118,7 @@
module->fixup_ports();
}
-std::string add_echos_to_abc_cmd(std::string str)
+std::string add_echos_to_abc9_cmd(std::string str)
{
std::string new_str, token;
for (size_t i = 0; i < str.size(); i++) {
@@ -140,7 +140,7 @@
return new_str;
}
-std::string fold_abc_cmd(std::string str)
+std::string fold_abc9_cmd(std::string str)
{
std::string token, new_str = " ";
int char_counter = 10;
@@ -184,7 +184,7 @@
return text;
}
-struct abc_output_filter
+struct abc9_output_filter
{
bool got_cr;
int escape_seq_state;
@@ -192,7 +192,7 @@
std::string tempdir_name;
bool show_tempdir;
- abc_output_filter(std::string tempdir_name, bool show_tempdir) : tempdir_name(tempdir_name), show_tempdir(show_tempdir)
+ abc9_output_filter(std::string tempdir_name, bool show_tempdir) : tempdir_name(tempdir_name), show_tempdir(show_tempdir)
{
got_cr = false;
escape_seq_state = 0;
@@ -247,7 +247,7 @@
bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
bool show_tempdir, std::string box_file, std::string lut_file,
- std::string wire_delay, const dict<int,IdString> &box_lookup
+ std::string wire_delay, const dict<int,IdString> &box_lookup, bool nomfs
)
{
module = current_module;
@@ -293,68 +293,72 @@
log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n",
module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str());
- std::string abc_script;
+ std::string abc9_script;
if (!lut_costs.empty()) {
- abc_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str());
+ abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str());
if (!box_file.empty())
- abc_script += stringf("read_box -v %s; ", box_file.c_str());
+ abc9_script += stringf("read_box -v %s; ", box_file.c_str());
}
else
if (!lut_file.empty()) {
- abc_script += stringf("read_lut %s; ", lut_file.c_str());
+ abc9_script += stringf("read_lut %s; ", lut_file.c_str());
if (!box_file.empty())
- abc_script += stringf("read_box -v %s; ", box_file.c_str());
+ abc9_script += stringf("read_box -v %s; ", box_file.c_str());
}
else
log_abort();
- abc_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str());
+ abc9_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str());
if (!script_file.empty()) {
if (script_file[0] == '+') {
for (size_t i = 1; i < script_file.size(); i++)
if (script_file[i] == '\'')
- abc_script += "'\\''";
+ abc9_script += "'\\''";
else if (script_file[i] == ',')
- abc_script += " ";
+ abc9_script += " ";
else
- abc_script += script_file[i];
+ abc9_script += script_file[i];
} else
- abc_script += stringf("source %s", script_file.c_str());
+ abc9_script += stringf("source %s", script_file.c_str());
} else if (!lut_costs.empty() || !lut_file.empty()) {
//bool all_luts_cost_same = true;
//for (int this_cost : lut_costs)
// if (this_cost != lut_costs.front())
// all_luts_cost_same = false;
- abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT;
+ abc9_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT;
//if (all_luts_cost_same && !fast_mode)
- // abc_script += "; lutpack {S}";
+ // abc9_script += "; lutpack {S}";
} else
log_abort();
//if (script_file.empty() && !delay_target.empty())
- // for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1))
- // abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8);
+ // for (size_t pos = abc9_script.find("dretime;"); pos != std::string::npos; pos = abc9_script.find("dretime;", pos+1))
+ // abc9_script = abc9_script.substr(0, pos) + "dretime; retime -o {D};" + abc9_script.substr(pos+8);
- for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos))
- abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3);
+ for (size_t pos = abc9_script.find("{D}"); pos != std::string::npos; pos = abc9_script.find("{D}", pos))
+ abc9_script = abc9_script.substr(0, pos) + delay_target + abc9_script.substr(pos+3);
- //for (size_t pos = abc_script.find("{S}"); pos != std::string::npos; pos = abc_script.find("{S}", pos))
- // abc_script = abc_script.substr(0, pos) + lutin_shared + abc_script.substr(pos+3);
+ //for (size_t pos = abc9_script.find("{S}"); pos != std::string::npos; pos = abc9_script.find("{S}", pos))
+ // abc9_script = abc9_script.substr(0, pos) + lutin_shared + abc9_script.substr(pos+3);
- for (size_t pos = abc_script.find("{W}"); pos != std::string::npos; pos = abc_script.find("{W}", pos))
- abc_script = abc_script.substr(0, pos) + wire_delay + abc_script.substr(pos+3);
+ for (size_t pos = abc9_script.find("{W}"); pos != std::string::npos; pos = abc9_script.find("{W}", pos))
+ abc9_script = abc9_script.substr(0, pos) + wire_delay + abc9_script.substr(pos+3);
- abc_script += stringf("; &write %s/output.aig", tempdir_name.c_str());
- abc_script = add_echos_to_abc_cmd(abc_script);
+ if (nomfs)
+ for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos))
+ abc9_script = abc9_script.erase(pos, strlen("&mfs"));
- for (size_t i = 0; i+1 < abc_script.size(); i++)
- if (abc_script[i] == ';' && abc_script[i+1] == ' ')
- abc_script[i+1] = '\n';
+ abc9_script += stringf("; &write %s/output.aig", tempdir_name.c_str());
+ abc9_script = add_echos_to_abc9_cmd(abc9_script);
+
+ for (size_t i = 0; i+1 < abc9_script.size(); i++)
+ if (abc9_script[i] == ';' && abc9_script[i+1] == ' ')
+ abc9_script[i+1] = '\n';
FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt");
- fprintf(f, "%s\n", abc_script.c_str());
+ fprintf(f, "%s\n", abc9_script.c_str());
fclose(f);
if (dff_mode || !clk_str.empty())
@@ -420,7 +424,7 @@
// the expose operation -- remove them from PO/PI
// and re-connecting them back together
for (auto wire : module->wires()) {
- auto it = wire->attributes.find(ID(abc_scc_break));
+ auto it = wire->attributes.find(ID(abc9_scc_break));
if (it != wire->attributes.end()) {
wire->attributes.erase(it);
log_assert(wire->port_output);
@@ -450,22 +454,22 @@
log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str());
#ifndef YOSYS_LINK_ABC
- abc_output_filter filt(tempdir_name, show_tempdir);
- int ret = run_command(buffer, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1));
+ abc9_output_filter filt(tempdir_name, show_tempdir);
+ int ret = run_command(buffer, std::bind(&abc9_output_filter::next_line, filt, std::placeholders::_1));
#else
// These needs to be mutable, supposedly due to getopt
- char *abc_argv[5];
+ char *abc9_argv[5];
string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str());
- abc_argv[0] = strdup(exe_file.c_str());
- abc_argv[1] = strdup("-s");
- abc_argv[2] = strdup("-f");
- abc_argv[3] = strdup(tmp_script_name.c_str());
- abc_argv[4] = 0;
- int ret = Abc_RealMain(4, abc_argv);
- free(abc_argv[0]);
- free(abc_argv[1]);
- free(abc_argv[2]);
- free(abc_argv[3]);
+ abc9_argv[0] = strdup(exe_file.c_str());
+ abc9_argv[1] = strdup("-s");
+ abc9_argv[2] = strdup("-f");
+ abc9_argv[3] = strdup(tmp_script_name.c_str());
+ abc9_argv[4] = 0;
+ int ret = Abc_RealMain(4, abc9_argv);
+ free(abc9_argv[0]);
+ free(abc9_argv[1]);
+ free(abc9_argv[2]);
+ free(abc9_argv[3]);
#endif
if (ret != 0)
log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret);
@@ -513,7 +517,7 @@
signal = std::move(bits);
}
- dict<IdString, bool> abc_box;
+ dict<IdString, bool> abc9_box;
vector<RTLIL::Cell*> boxes;
for (const auto &it : module->cells_) {
auto cell = it.second;
@@ -521,10 +525,10 @@
module->remove(cell);
continue;
}
- auto jt = abc_box.find(cell->type);
- if (jt == abc_box.end()) {
+ auto jt = abc9_box.find(cell->type);
+ if (jt == abc9_box.end()) {
RTLIL::Module* box_module = design->module(cell->type);
- jt = abc_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc_box_id)))).first;
+ jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first;
}
if (jt->second)
boxes.emplace_back(cell);
@@ -648,7 +652,7 @@
if (!conn.second.is_wire())
continue;
Wire *wire = conn.second.as_wire();
- if (!wire->get_bool_attribute(ID(abc_padding)))
+ if (!wire->get_bool_attribute(ID(abc9_padding)))
continue;
cell->unsetPort(conn.first);
log_debug("Dropping padded port connection for %s (%s) .%s (%s )\n", log_id(cell), cell->type.c_str(), log_id(conn.first), log_signal(conn.second));
@@ -827,17 +831,17 @@
log(" if no -script parameter is given, the following scripts are used:\n");
log("\n");
log(" for -lut/-luts (only one LUT size):\n");
- log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str());
+ log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str());
log("\n");
log(" for -lut/-luts (different LUT sizes):\n");
- log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT).c_str());
+ log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str());
log("\n");
log(" -fast\n");
log(" use different default scripts that are slightly faster (at the cost\n");
log(" of output quality):\n");
log("\n");
log(" for -lut/-luts:\n");
- log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_LUT).c_str());
+ log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str());
log("\n");
log(" -D <picoseconds>\n");
log(" set delay target. the string {D} in the default scripts above is\n");
@@ -921,6 +925,7 @@
std::string delay_target, lutin_shared = "-S 1", wire_delay;
bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
bool show_tempdir = false;
+ bool nomfs = false;
vector<int> lut_costs;
markgroups = false;
@@ -1043,6 +1048,10 @@
wire_delay = "-W " + args[++argidx];
continue;
}
+ if (arg == "-nomfs") {
+ nomfs = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -1057,7 +1066,7 @@
dict<int,IdString> box_lookup;
for (auto m : design->modules()) {
- auto it = m->attributes.find(ID(abc_box_id));
+ auto it = m->attributes.find(ID(abc9_box_id));
if (it == m->attributes.end())
continue;
if (m->name.begins_with("$paramod"))
@@ -1065,7 +1074,7 @@
auto id = it->second.as_int();
auto r = box_lookup.insert(std::make_pair(id, m->name));
if (!r.second)
- log_error("Module '%s' has the same abc_box_id = %d value as '%s'.\n",
+ log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n",
log_id(m), id, log_id(r.first->second));
log_assert(r.second);
@@ -1073,24 +1082,24 @@
for (auto p : m->ports) {
auto w = m->wire(p);
log_assert(w);
- if (w->attributes.count(ID(abc_carry))) {
+ if (w->attributes.count(ID(abc9_carry))) {
if (w->port_input) {
if (carry_in)
- log_error("Module '%s' contains more than one 'abc_carry' input port.\n", log_id(m));
+ log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m));
carry_in = w;
}
else if (w->port_output) {
if (carry_out)
- log_error("Module '%s' contains more than one 'abc_carry' input port.\n", log_id(m));
+ log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m));
carry_out = w;
}
}
}
if (carry_in || carry_out) {
if (carry_in && !carry_out)
- log_error("Module '%s' contains an 'abc_carry' input port but no output port.\n", log_id(m));
+ log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m));
if (!carry_in && carry_out)
- log_error("Module '%s' contains an 'abc_carry' output port but no input port.\n", log_id(m));
+ log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m));
// Make carry_in the last PI, and carry_out the last PO
// since ABC requires it this way
auto &ports = m->ports;
@@ -1118,7 +1127,7 @@
for (auto mod : design->selected_modules())
{
- if (mod->attributes.count(ID(abc_box_id)))
+ if (mod->attributes.count(ID(abc9_box_id)))
continue;
if (mod->processes.size() > 0) {
@@ -1131,7 +1140,7 @@
if (!dff_mode || !clk_str.empty()) {
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
delay_target, lutin_shared, fast_mode, show_tempdir,
- box_file, lut_file, wire_delay, box_lookup);
+ box_file, lut_file, wire_delay, box_lookup, nomfs);
continue;
}
@@ -1277,7 +1286,7 @@
en_sig = assign_map(std::get<3>(it.first));
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$",
keepff, delay_target, lutin_shared, fast_mode, show_tempdir,
- box_file, lut_file, wire_delay, box_lookup);
+ box_file, lut_file, wire_delay, box_lookup, nomfs);
assign_map.set(mod);
}
}
diff --git a/passes/techmap/aigmap.cc b/passes/techmap/aigmap.cc
index 1d5e128..2ecb2f3 100644
--- a/passes/techmap/aigmap.cc
+++ b/passes/techmap/aigmap.cc
@@ -27,6 +27,7 @@
AigmapPass() : Pass("aigmap", "map logic to and-inverter-graph circuit") { }
void help() YS_OVERRIDE
{
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" aigmap [options] [selection]\n");
log("\n");
@@ -36,10 +37,15 @@
log(" -nand\n");
log(" Enable creation of $_NAND_ cells\n");
log("\n");
+ log(" -select\n");
+ log(" Overwrite replaced cells in the current selection with new $_AND_,\n");
+ log(" $_NOT_, and $_NAND_, cells\n");
+
+ log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
- bool nand_mode = false;
+ bool nand_mode = false, select_mode = false;
log_header(design, "Executing AIGMAP pass (map logic to AIG).\n");
@@ -50,6 +56,10 @@
nand_mode = true;
continue;
}
+ if (args[argidx] == "-select") {
+ select_mode = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -62,6 +72,7 @@
dict<IdString, int> stat_not_replaced;
int orig_num_cells = GetSize(module->cells());
+ pool<IdString> new_sel;
for (auto cell : module->selected_cells())
{
Aig aig(cell);
@@ -75,6 +86,8 @@
if (aig.name.empty()) {
not_replaced_count++;
stat_not_replaced[cell->type]++;
+ if (select_mode)
+ new_sel.insert(cell->name);
continue;
}
@@ -95,19 +108,33 @@
SigBit A = sigs.at(node.left_parent);
SigBit B = sigs.at(node.right_parent);
if (nand_mode && node.inverter) {
- bit = module->NandGate(NEW_ID, A, B);
+ bit = module->addWire(NEW_ID);
+ auto gate = module->addNandGate(NEW_ID, A, B, bit);
+ if (select_mode)
+ new_sel.insert(gate->name);
+
goto skip_inverter;
} else {
pair<int, int> key(node.left_parent, node.right_parent);
if (and_cache.count(key))
bit = and_cache.at(key);
- else
- bit = module->AndGate(NEW_ID, A, B);
+ else {
+ bit = module->addWire(NEW_ID);
+ auto gate = module->addAndGate(NEW_ID, A, B, bit);
+ if (select_mode)
+ new_sel.insert(gate->name);
+ }
}
}
- if (node.inverter)
- bit = module->NotGate(NEW_ID, bit);
+ if (node.inverter) {
+ SigBit new_bit = module->addWire(NEW_ID);
+ auto gate = module->addNotGate(NEW_ID, bit, new_bit);
+ bit = new_bit;
+ if (select_mode)
+ new_sel.insert(gate->name);
+
+ }
skip_inverter:
for (auto &op : node.outports)
@@ -142,6 +169,13 @@
for (auto cell : replaced_cells)
module->remove(cell);
+
+ if (select_mode) {
+ log_assert(!design->selection_stack.empty());
+ RTLIL::Selection& sel = design->selection_stack.back();
+ sel.selected_members[module->name] = std::move(new_sel);
+ }
+
}
}
} AigmapPass;
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index 08a1af2..0c57733 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -257,6 +257,12 @@
w->add_strpool_attribute(ID(src), extra_src_attrs);
}
design->select(module, w);
+
+ if (it.second->name.begins_with("\\_TECHMAP_REPLACE_.")) {
+ IdString replace_name = stringf("%s%s", orig_cell_name.c_str(), it.second->name.c_str() + strlen("\\_TECHMAP_REPLACE_"));
+ Wire *replace_w = module->addWire(replace_name, it.second);
+ module->connect(replace_w, w);
+ }
}
SigMap tpl_sigmap(tpl);
@@ -378,6 +384,8 @@
if (techmap_replace_cell)
c_name = orig_cell_name;
+ else if (it.second->name.begins_with("\\_TECHMAP_REPLACE_."))
+ c_name = stringf("%s%s", orig_cell_name.c_str(), c_name.c_str() + strlen("\\_TECHMAP_REPLACE_"));
else
apply_prefix(cell->name, c_name);
@@ -1198,6 +1206,12 @@
log("\n");
log("A cell with the name _TECHMAP_REPLACE_ in the map file will inherit the name\n");
log("and attributes of the cell that is being replaced.\n");
+ log("A cell with a name of the form `_TECHMAP_REPLACE_.<suffix>` in the map file will\n");
+ log("be named thus but with the `_TECHMAP_REPLACE_' prefix substituted with the name\n");
+ log("of the cell being replaced.\n");
+ log("Similarly, a wire named in the form `_TECHMAP_REPLACE_.<suffix>` will cause a\n");
+ log("new wire alias to be created and named as above but with the `_TECHMAP_REPLACE_'\n");
+ log("prefix also substituted.\n");
log("\n");
log("See 'help extract' for a pass that does the opposite thing.\n");
log("\n");
diff --git a/techlibs/ecp5/.gitignore b/techlibs/ecp5/.gitignore
index 54c3297..9d47232 100644
--- a/techlibs/ecp5/.gitignore
+++ b/techlibs/ecp5/.gitignore
@@ -6,4 +6,5 @@
bram_conn_4.vh
bram_conn_9.vh
bram_conn_18.vh
+bram_conn_36.vh
brams_connect.mk
diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc
index 80eee50..5832d07 100644
--- a/techlibs/ecp5/Makefile.inc
+++ b/techlibs/ecp5/Makefile.inc
@@ -15,12 +15,12 @@
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_map.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dsp_map.v))
-$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_map.v))
-$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_unmap.v))
-$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_model.v))
-$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_5g.box))
-$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_5g.lut))
-$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_5g_nowide.lut))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_map.v))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_unmap.v))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_model.v))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_5g.box))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_5g.lut))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_5g_nowide.lut))
EXTRA_OBJS += techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk
.SECONDARY: techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk
@@ -44,6 +44,7 @@
techlibs/ecp5/bram_conn_4.vh: techlibs/ecp5/brams_connect.mk
techlibs/ecp5/bram_conn_9.vh: techlibs/ecp5/brams_connect.mk
techlibs/ecp5/bram_conn_18.vh: techlibs/ecp5/brams_connect.mk
+techlibs/ecp5/bram_conn_36.vh: techlibs/ecp5/brams_connect.mk
$(eval $(call add_gen_share_file,share/ecp5,techlibs/ecp5/bram_init_1_2_4.vh))
$(eval $(call add_gen_share_file,share/ecp5,techlibs/ecp5/bram_init_9_18_36.vh))
@@ -53,3 +54,4 @@
$(eval $(call add_gen_share_file,share/ecp5,techlibs/ecp5/bram_conn_4.vh))
$(eval $(call add_gen_share_file,share/ecp5,techlibs/ecp5/bram_conn_9.vh))
$(eval $(call add_gen_share_file,share/ecp5,techlibs/ecp5/bram_conn_18.vh))
+$(eval $(call add_gen_share_file,share/ecp5,techlibs/ecp5/bram_conn_36.vh))
diff --git a/techlibs/ecp5/abc_5g.box b/techlibs/ecp5/abc9_5g.box
similarity index 96%
rename from techlibs/ecp5/abc_5g.box
rename to techlibs/ecp5/abc9_5g.box
index a336b4a..2bc945a 100644
--- a/techlibs/ecp5/abc_5g.box
+++ b/techlibs/ecp5/abc9_5g.box
@@ -18,7 +18,7 @@
# Box 2 : TRELLIS_DPR16X4_COMB (16x4 dist ram)
# Outputs: DO0, DO1, DO2, DO3
# name ID w/b ins outs
-$__ABC_DPR16X4_COMB 2 0 8 4
+$__ABC9_DPR16X4_COMB 2 0 8 4
#A0 A1 A2 A3 RAD0 RAD1 RAD2 RAD3
0 0 0 0 141 379 275 379
diff --git a/techlibs/ecp5/abc_5g.lut b/techlibs/ecp5/abc9_5g.lut
similarity index 100%
rename from techlibs/ecp5/abc_5g.lut
rename to techlibs/ecp5/abc9_5g.lut
diff --git a/techlibs/ecp5/abc_5g_nowide.lut b/techlibs/ecp5/abc9_5g_nowide.lut
similarity index 100%
rename from techlibs/ecp5/abc_5g_nowide.lut
rename to techlibs/ecp5/abc9_5g_nowide.lut
diff --git a/techlibs/ecp5/abc_map.v b/techlibs/ecp5/abc9_map.v
similarity index 89%
rename from techlibs/ecp5/abc_map.v
rename to techlibs/ecp5/abc9_map.v
index ffd25f0..d8d70f9 100644
--- a/techlibs/ecp5/abc_map.v
+++ b/techlibs/ecp5/abc9_map.v
@@ -20,5 +20,5 @@
.RAD(RAD), .DO(\$DO )
);
- \$__ABC_DPR16X4_COMB do (.A(\$DO ), .S(RAD), .Y(DO));
+ \$__ABC9_DPR16X4_COMB do (.A(\$DO ), .S(RAD), .Y(DO));
endmodule
diff --git a/techlibs/ecp5/abc9_model.v b/techlibs/ecp5/abc9_model.v
new file mode 100644
index 0000000..1dc8b56
--- /dev/null
+++ b/techlibs/ecp5/abc9_model.v
@@ -0,0 +1,5 @@
+// ---------------------------------------
+
+(* abc9_box_id=2 *)
+module \$__ABC9_DPR16X4_COMB (input [3:0] A, S, output [3:0] Y);
+endmodule
diff --git a/techlibs/ecp5/abc9_unmap.v b/techlibs/ecp5/abc9_unmap.v
new file mode 100644
index 0000000..9ae143c
--- /dev/null
+++ b/techlibs/ecp5/abc9_unmap.v
@@ -0,0 +1,5 @@
+// ---------------------------------------
+
+module \$__ABC9_DPR16X4_COMB (input [3:0] A, S, output [3:0] Y);
+ assign Y = A;
+endmodule
diff --git a/techlibs/ecp5/abc_model.v b/techlibs/ecp5/abc_model.v
deleted file mode 100644
index 56a733b..0000000
--- a/techlibs/ecp5/abc_model.v
+++ /dev/null
@@ -1,5 +0,0 @@
-// ---------------------------------------
-
-(* abc_box_id=2 *)
-module \$__ABC_DPR16X4_COMB (input [3:0] A, S, output [3:0] Y);
-endmodule
diff --git a/techlibs/ecp5/abc_unmap.v b/techlibs/ecp5/abc_unmap.v
deleted file mode 100644
index d43cdd9..0000000
--- a/techlibs/ecp5/abc_unmap.v
+++ /dev/null
@@ -1,5 +0,0 @@
-// ---------------------------------------
-
-module \$__ABC_DPR16X4_COMB (input [3:0] A, S, output [3:0] Y);
- assign Y = A;
-endmodule
diff --git a/techlibs/ecp5/bram.txt b/techlibs/ecp5/bram.txt
index f223a42..777ccaa 100644
--- a/techlibs/ecp5/bram.txt
+++ b/techlibs/ecp5/bram.txt
@@ -1,3 +1,18 @@
+bram $__ECP5_PDPW16KD
+ init 1
+
+ abits 9
+ dbits 36
+
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ enable 4 1
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
bram $__ECP5_DP16KD
init 1
@@ -22,8 +37,16 @@
clkpol 2 3
endbram
+match $__ECP5_PDPW16KD
+ min bits 2048
+ min efficiency 5
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
match $__ECP5_DP16KD
min bits 2048
min efficiency 5
- shuffle_enable B
+ shuffle_enable A
endmatch
diff --git a/techlibs/ecp5/brams_connect.py b/techlibs/ecp5/brams_connect.py
index f86dcfc..098607c 100755
--- a/techlibs/ecp5/brams_connect.py
+++ b/techlibs/ecp5/brams_connect.py
@@ -10,6 +10,18 @@
print(" %s," % ", ".join(dia_conn), file=f)
print(" %s," % ", ".join(dob_conn), file=f)
+def write_bus_ports_pdp(f, adw_bits, adr_bits, di_bits, do_bits, be_bits):
+ adw_conn = [".ADW%d(%s)" % (i, adw_bits[i]) for i in range(len(adw_bits))]
+ adr_conn = [".ADR%d(%s)" % (i, adr_bits[i]) for i in range(len(adr_bits))]
+ di_conn = [".DI%d(%s)" % (i, di_bits[i]) for i in range(len(di_bits))]
+ do_conn = [".DO%d(%s)" % (i, do_bits[i]) for i in range(len(do_bits))]
+ be_conn = [".BE%d(%s)" % (i, be_bits[i]) for i in range(len(be_bits))]
+ print(" %s," % ", ".join(adw_conn), file=f)
+ print(" %s," % ", ".join(adr_conn), file=f)
+ print(" %s," % ", ".join(di_conn), file=f)
+ print(" %s," % ", ".join(do_conn), file=f)
+ print(" %s," % ", ".join(be_conn), file=f)
+
with open("techlibs/ecp5/bram_conn_1.vh", "w") as f:
ada_bits = ["A1ADDR[%d]" % i for i in range(14)]
adb_bits = ["B1ADDR[%d]" % i for i in range(14)]
@@ -44,3 +56,11 @@
dia_bits = ["A1DATA[%d]" % i for i in range(18)]
dob_bits = ["B1DATA[%d]" % i for i in range(18)]
write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits)
+
+with open("techlibs/ecp5/bram_conn_36.vh", "w") as f:
+ adw_bits = ["A1ADDR[%d]" % i for i in range(9)]
+ adr_bits = ["1'b0", "1'b0", "1'b0", "1'b0", "1'b0"] + ["B1ADDR[%d]" % i for i in range(9)]
+ di_bits = ["A1DATA[%d]" % i for i in range(36)]
+ do_bits = ["B1DATA[%d]" % (i + 18) for i in range(18)] + ["B1DATA[%d]" % i for i in range(18)]
+ be_bits = ["A1EN[%d]" % i for i in range(4)]
+ write_bus_ports_pdp(f, adw_bits, adr_bits, di_bits, do_bits, be_bits)
diff --git a/techlibs/ecp5/brams_map.v b/techlibs/ecp5/brams_map.v
index 0353cba..310aeda 100644
--- a/techlibs/ecp5/brams_map.v
+++ b/techlibs/ecp5/brams_map.v
@@ -113,3 +113,45 @@
wire TECHMAP_FAIL = 1'b1;
end endgenerate
endmodule
+
+module \$__ECP5_PDPW16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 9;
+ parameter CFG_DBITS = 36;
+ parameter CFG_ENABLE_A = 4;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+ parameter [18431:0] INIT = 18432'bx;
+
+ input CLK2;
+ input CLK3;
+
+ input [CFG_ABITS-1:0] A1ADDR;
+ input [CFG_DBITS-1:0] A1DATA;
+ input [CFG_ENABLE_A-1:0] A1EN;
+
+ input [CFG_ABITS-1:0] B1ADDR;
+ output [CFG_DBITS-1:0] B1DATA;
+ input B1EN;
+
+ localparam CLKWMUX = CLKPOL2 ? "CLKA" : "INV";
+ localparam CLKRMUX = CLKPOL3 ? "CLKB" : "INV";
+
+ localparam WRITEMODE_A = TRANSP2 ? "WRITETHROUGH" : "READBEFOREWRITE";
+
+ PDPW16KD #(
+ `include "bram_init_9_18_36.vh"
+ .DATA_WIDTH_W(36),
+ .DATA_WIDTH_R(36),
+ .CLKWMUX(CLKWMUX),
+ .CLKRMUX(CLKRMUX),
+ .GSR("AUTO")
+ ) _TECHMAP_REPLACE_ (
+ `include "bram_conn_36.vh"
+ .CLKW(CLK2), .CLKR(CLK3),
+ .CEW(1'b1),
+ .CER(B1EN), .OCER(1'b1),
+ .RST(1'b0)
+ );
+
+endmodule
diff --git a/techlibs/ecp5/cells_bb.v b/techlibs/ecp5/cells_bb.v
index 8557053..0a5046d 100644
--- a/techlibs/ecp5/cells_bb.v
+++ b/techlibs/ecp5/cells_bb.v
@@ -683,4 +683,98 @@
module SGSR (
input GSR, CLK
);
-endmodule
\ No newline at end of file
+endmodule
+
+
+(* blackbox *)
+module PDPW16KD (
+ input DI35, DI34, DI33, DI32, DI31, DI30, DI29, DI28, DI27, DI26, DI25, DI24, DI23, DI22, DI21, DI20, DI19, DI18,
+ input DI17, DI16, DI15, DI14, DI13, DI12, DI11, DI10, DI9, DI8, DI7, DI6, DI5, DI4, DI3, DI2, DI1, DI0,
+ input ADW8, ADW7, ADW6, ADW5, ADW4, ADW3, ADW2, ADW1, ADW0,
+ input BE3, BE2, BE1, BE0, CEW, CLKW, CSW2, CSW1, CSW0,
+ input ADR13, ADR12, ADR11, ADR10, ADR9, ADR8, ADR7, ADR6, ADR5, ADR4, ADR3, ADR2, ADR1, ADR0,
+ input CER, OCER, CLKR, CSR2, CSR1, CSR0, RST,
+ output DO35, DO34, DO33, DO32, DO31, DO30, DO29, DO28, DO27, DO26, DO25, DO24, DO23, DO22, DO21, DO20, DO19, DO18,
+ output DO17, DO16, DO15, DO14, DO13, DO12, DO11, DO10, DO9, DO8, DO7, DO6, DO5, DO4, DO3, DO2, DO1, DO0
+);
+ parameter DATA_WIDTH_W = 36;
+ parameter DATA_WIDTH_R = 36;
+ parameter GSR = "ENABLED";
+
+ parameter REGMODE = "NOREG";
+
+ parameter RESETMODE = "SYNC";
+ parameter ASYNC_RESET_RELEASE = "SYNC";
+
+ parameter CSDECODE_W = "0b000";
+ parameter CSDECODE_R = "0b000";
+
+ parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_DATA = "STATIC";
+ parameter CLKWMUX = "CLKW";
+ parameter CLKRMUX = "CLKR";
+
+endmodule
diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v
index db77dc1..f467218 100644
--- a/techlibs/ecp5/cells_sim.v
+++ b/techlibs/ecp5/cells_sim.v
@@ -9,19 +9,19 @@
endmodule
// ---------------------------------------
-(* abc_box_id=4, lib_whitebox *)
+(* abc9_box_id=4, lib_whitebox *)
module L6MUX21 (input D0, D1, SD, output Z);
assign Z = SD ? D1 : D0;
endmodule
// ---------------------------------------
-(* abc_box_id=1, lib_whitebox *)
+(* abc9_box_id=1, lib_whitebox *)
module CCU2C(
- (* abc_carry *)
+ (* abc9_carry *)
input CIN,
input A0, B0, C0, D0, A1, B1, C1, D1,
output S0, S1,
- (* abc_carry *)
+ (* abc9_carry *)
output COUT
);
parameter [15:0] INIT0 = 16'h0000;
@@ -103,7 +103,7 @@
endmodule
// ---------------------------------------
-(* abc_box_id=3, lib_whitebox *)
+(* abc9_box_id=3, lib_whitebox *)
module PFUMX (input ALUT, BLUT, C0, output Z);
assign Z = C0 ? ALUT : BLUT;
endmodule
@@ -115,7 +115,7 @@
input WRE,
input WCK,
input [3:0] RAD,
- /* (* abc_arrival=<TODO> *) */
+ /* (* abc9_arrival=<TODO> *) */
output [3:0] DO
);
parameter WCKMUX = "WCK";
diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc
index 1f5b1cb..80aa1db 100644
--- a/techlibs/ecp5/synth_ecp5.cc
+++ b/techlibs/ecp5/synth_ecp5.cc
@@ -307,15 +307,16 @@
}
std::string techmap_args = "-map +/ecp5/latches_map.v";
if (abc9)
- techmap_args += " -map +/ecp5/abc_map.v -max_iter 1";
+ techmap_args += " -map +/ecp5/abc9_map.v -max_iter 1";
run("techmap " + techmap_args);
if (abc9) {
+ run("read_verilog -icells -lib +/ecp5/abc9_model.v");
if (nowidelut)
- run("abc9 -lut +/ecp5/abc_5g_nowide.lut -box +/ecp5/abc_5g.box -W 200");
+ run("abc9 -lut +/ecp5/abc9_5g_nowide.lut -box +/ecp5/abc9_5g.box -W 200");
else
- run("abc9 -lut +/ecp5/abc_5g.lut -box +/ecp5/abc_5g.box -W 200");
- run("techmap -map +/ecp5/abc_unmap.v");
+ run("abc9 -lut +/ecp5/abc9_5g.lut -box +/ecp5/abc9_5g.box -W 200");
+ run("techmap -map +/ecp5/abc9_unmap.v");
} else {
if (nowidelut)
run("abc -lut 4 -dress");
diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc
index 92a9956..3c33fcb 100644
--- a/techlibs/ice40/Makefile.inc
+++ b/techlibs/ice40/Makefile.inc
@@ -28,12 +28,13 @@
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt))
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v))
$(eval $(call add_share_file,share/ice40,techlibs/ice40/dsp_map.v))
-$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_hx.box))
-$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_hx.lut))
-$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_lp.box))
-$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_lp.lut))
-$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_u.box))
-$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_u.lut))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_model.v))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_hx.box))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_hx.lut))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_lp.box))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_lp.lut))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_u.box))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_u.lut))
$(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init1.vh))
$(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init2.vh))
diff --git a/techlibs/ice40/abc_hx.box b/techlibs/ice40/abc9_hx.box
similarity index 100%
rename from techlibs/ice40/abc_hx.box
rename to techlibs/ice40/abc9_hx.box
diff --git a/techlibs/ice40/abc_hx.lut b/techlibs/ice40/abc9_hx.lut
similarity index 100%
rename from techlibs/ice40/abc_hx.lut
rename to techlibs/ice40/abc9_hx.lut
diff --git a/techlibs/ice40/abc_lp.box b/techlibs/ice40/abc9_lp.box
similarity index 100%
rename from techlibs/ice40/abc_lp.box
rename to techlibs/ice40/abc9_lp.box
diff --git a/techlibs/ice40/abc_lp.lut b/techlibs/ice40/abc9_lp.lut
similarity index 100%
rename from techlibs/ice40/abc_lp.lut
rename to techlibs/ice40/abc9_lp.lut
diff --git a/techlibs/ice40/abc9_model.v b/techlibs/ice40/abc9_model.v
new file mode 100644
index 0000000..26cf6cc
--- /dev/null
+++ b/techlibs/ice40/abc9_model.v
@@ -0,0 +1,27 @@
+(* abc9_box_id = 1, lib_whitebox *)
+module \$__ICE40_CARRY_WRAPPER (
+ (* abc9_carry *)
+ output CO,
+ output O,
+ input A, B,
+ (* abc9_carry *)
+ input CI,
+ input I0, I3
+);
+ parameter LUT = 0;
+ SB_CARRY carry (
+ .I0(A),
+ .I1(B),
+ .CI(CI),
+ .CO(CO)
+ );
+ SB_LUT4 #(
+ .LUT_INIT(LUT)
+ ) adder (
+ .I0(I0),
+ .I1(A),
+ .I2(B),
+ .I3(I3),
+ .O(O)
+ );
+endmodule
diff --git a/techlibs/ice40/abc_u.box b/techlibs/ice40/abc9_u.box
similarity index 100%
rename from techlibs/ice40/abc_u.box
rename to techlibs/ice40/abc9_u.box
diff --git a/techlibs/ice40/abc_u.lut b/techlibs/ice40/abc9_u.lut
similarity index 100%
rename from techlibs/ice40/abc_u.lut
rename to techlibs/ice40/abc9_u.lut
diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v
index 8e5e035..f9e79a6 100644
--- a/techlibs/ice40/cells_sim.v
+++ b/techlibs/ice40/cells_sim.v
@@ -2,9 +2,9 @@
`define SB_DFF_REG reg Q = 0
// `define SB_DFF_REG reg Q
-`define ABC_ARRIVAL_HX(TIME) `ifdef ICE40_HX (* abc_arrival=TIME *) `endif
-`define ABC_ARRIVAL_LP(TIME) `ifdef ICE40_LP (* abc_arrival=TIME *) `endif
-`define ABC_ARRIVAL_U(TIME) `ifdef ICE40_U (* abc_arrival=TIME *) `endif
+`define ABC9_ARRIVAL_HX(TIME) `ifdef ICE40_HX (* abc9_arrival=TIME *) `endif
+`define ABC9_ARRIVAL_LP(TIME) `ifdef ICE40_LP (* abc9_arrival=TIME *) `endif
+`define ABC9_ARRIVAL_U(TIME) `ifdef ICE40_U (* abc9_arrival=TIME *) `endif
// SiliconBlue IO Cells
@@ -145,34 +145,6 @@
assign CO = (I0 && I1) || ((I0 || I1) && CI);
endmodule
-(* abc_box_id = 1, lib_whitebox *)
-module \$__ICE40_CARRY_WRAPPER (
- (* abc_carry *)
- output CO,
- output O,
- input A, B,
- (* abc_carry *)
- input CI,
- input I0, I3
-);
- parameter LUT = 0;
- SB_CARRY carry (
- .I0(A),
- .I1(B),
- .CI(CI),
- .CO(CO)
- );
- SB_LUT4 #(
- .LUT_INIT(LUT)
- ) adder (
- .I0(I0),
- .I1(A),
- .I2(B),
- .I3(I3),
- .O(O)
- );
-endmodule
-
// Max delay from: https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
@@ -180,9 +152,9 @@
// Positive Edge SiliconBlue FF Cells
module SB_DFF (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, D
);
@@ -191,9 +163,9 @@
endmodule
module SB_DFFE (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, D
);
@@ -203,9 +175,9 @@
endmodule
module SB_DFFSR (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, R, D
);
@@ -217,9 +189,9 @@
endmodule
module SB_DFFR (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, R, D
);
@@ -231,9 +203,9 @@
endmodule
module SB_DFFSS (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, S, D
);
@@ -245,9 +217,9 @@
endmodule
module SB_DFFS (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, S, D
);
@@ -259,9 +231,9 @@
endmodule
module SB_DFFESR (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, R, D
);
@@ -275,9 +247,9 @@
endmodule
module SB_DFFER (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, R, D
);
@@ -289,9 +261,9 @@
endmodule
module SB_DFFESS (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, S, D
);
@@ -305,9 +277,9 @@
endmodule
module SB_DFFES (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, S, D
);
@@ -321,9 +293,9 @@
// Negative Edge SiliconBlue FF Cells
module SB_DFFN (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, D
);
@@ -332,9 +304,9 @@
endmodule
module SB_DFFNE (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, D
);
@@ -344,9 +316,9 @@
endmodule
module SB_DFFNSR (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, R, D
);
@@ -358,9 +330,9 @@
endmodule
module SB_DFFNR (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, R, D
);
@@ -372,9 +344,9 @@
endmodule
module SB_DFFNSS (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, S, D
);
@@ -386,9 +358,9 @@
endmodule
module SB_DFFNS (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, S, D
);
@@ -400,9 +372,9 @@
endmodule
module SB_DFFNESR (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, R, D
);
@@ -416,9 +388,9 @@
endmodule
module SB_DFFNER (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, R, D
);
@@ -430,9 +402,9 @@
endmodule
module SB_DFFNESS (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, S, D
);
@@ -446,9 +418,9 @@
endmodule
module SB_DFFNES (
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, S, D
);
@@ -462,9 +434,9 @@
// SiliconBlue RAM Cells
module SB_RAM40_4K (
- `ABC_ARRIVAL_HX(2146) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
- `ABC_ARRIVAL_LP(3163) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
- `ABC_ARRIVAL_U(1179) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
+ `ABC9_ARRIVAL_HX(2146) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
+ `ABC9_ARRIVAL_LP(3163) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
+ `ABC9_ARRIVAL_U(1179) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
output [15:0] RDATA,
input RCLK, RCLKE, RE,
input [10:0] RADDR,
@@ -633,9 +605,9 @@
endmodule
module SB_RAM40_4KNR (
- `ABC_ARRIVAL_HX(2146) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
- `ABC_ARRIVAL_LP(3163) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
- `ABC_ARRIVAL_U(1179) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
+ `ABC9_ARRIVAL_HX(2146) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
+ `ABC9_ARRIVAL_LP(3163) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
+ `ABC9_ARRIVAL_U(1179) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
output [15:0] RDATA,
input RCLKN, RCLKE, RE,
input [10:0] RADDR,
@@ -701,9 +673,9 @@
endmodule
module SB_RAM40_4KNW (
- `ABC_ARRIVAL_HX(2146) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
- `ABC_ARRIVAL_LP(3163) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
- `ABC_ARRIVAL_U(1179) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
+ `ABC9_ARRIVAL_HX(2146) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
+ `ABC9_ARRIVAL_LP(3163) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
+ `ABC9_ARRIVAL_U(1179) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
output [15:0] RDATA,
input RCLK, RCLKE, RE,
input [10:0] RADDR,
@@ -769,9 +741,9 @@
endmodule
module SB_RAM40_4KNRNW (
- `ABC_ARRIVAL_HX(2146) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
- `ABC_ARRIVAL_LP(3163) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
- `ABC_ARRIVAL_U(1179) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
+ `ABC9_ARRIVAL_HX(2146) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
+ `ABC9_ARRIVAL_LP(3163) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
+ `ABC9_ARRIVAL_U(1179) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
output [15:0] RDATA,
input RCLKN, RCLKE, RE,
input [10:0] RADDR,
@@ -841,9 +813,9 @@
module ICESTORM_LC (
input I0, I1, I2, I3, CIN, CLK, CEN, SR,
output LO,
- `ABC_ARRIVAL_HX(540)
- `ABC_ARRIVAL_LP(796)
- `ABC_ARRIVAL_U(1391)
+ `ABC9_ARRIVAL_HX(540)
+ `ABC9_ARRIVAL_LP(796)
+ `ABC9_ARRIVAL_U(1391)
output O,
output COUT
);
@@ -1445,7 +1417,6 @@
input ADDSUBTOP, ADDSUBBOT,
input OHOLDTOP, OHOLDBOT,
input CI, ACCUMCI, SIGNEXTIN,
- //`ABC_ARRIVAL_U(1984) // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
output [31:0] O,
output CO, ACCUMCO, SIGNEXTOUT
);
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index 841f102..b66c6bf 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -245,7 +245,7 @@
define = "-D ICE40_U";
else
define = "-D ICE40_HX";
- run("read_verilog -icells " + define + " -lib +/ice40/cells_sim.v");
+ run("read_verilog " + define + " -lib +/ice40/cells_sim.v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
run("proc");
}
@@ -349,6 +349,7 @@
}
if (!noabc) {
if (abc == "abc9") {
+ run("read_verilog -icells -lib +/ice40/abc9_model.v");
int wire_delay;
if (device_opt == "lp")
wire_delay = 400;
@@ -356,7 +357,7 @@
wire_delay = 750;
else
wire_delay = 250;
- run(abc + stringf(" -W %d -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", wire_delay, device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)");
+ run(abc + stringf(" -W %d -lut +/ice40/abc9_%s.lut -box +/ice40/abc9_%s.box", wire_delay, device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)");
}
else
run(abc + " -dress -lut 4", "(skip if -noabc)");
diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc
index ae82311..0ae67d9 100644
--- a/techlibs/xilinx/Makefile.inc
+++ b/techlibs/xilinx/Makefile.inc
@@ -44,12 +44,12 @@
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/dsp_map.v))
-$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_map.v))
-$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_unmap.v))
-$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_model.v))
-$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.box))
-$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.lut))
-$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7_nowide.lut))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_map.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_unmap.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_model.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_xc7.box))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_xc7.lut))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_xc7_nowide.lut))
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh))
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh))
diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc9_map.v
similarity index 88%
rename from techlibs/xilinx/abc_map.v
rename to techlibs/xilinx/abc9_map.v
index e497609..0eac08f 100644
--- a/techlibs/xilinx/abc_map.v
+++ b/techlibs/xilinx/abc9_map.v
@@ -39,8 +39,8 @@
.A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4),
.DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4)
);
- \$__ABC_LUT6 dpo (.A(\$DPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(DPO));
- \$__ABC_LUT6 spo (.A(\$SPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(SPO));
+ \$__ABC9_LUT6 dpo (.A(\$DPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(DPO));
+ \$__ABC9_LUT6 spo (.A(\$SPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(SPO));
endmodule
module RAM64X1D (
@@ -62,8 +62,8 @@
.A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .A5(A5),
.DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4), .DPRA5(DPRA5)
);
- \$__ABC_LUT6 dpo (.A(\$DPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(DPO));
- \$__ABC_LUT6 spo (.A(\$SPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(SPO));
+ \$__ABC9_LUT6 dpo (.A(\$DPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(DPO));
+ \$__ABC9_LUT6 spo (.A(\$SPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(SPO));
endmodule
module RAM128X1D (
@@ -84,8 +84,8 @@
.A(A),
.DPRA(DPRA)
);
- \$__ABC_LUT7 dpo (.A(\$DPO ), .S(A), .Y(DPO));
- \$__ABC_LUT7 spo (.A(\$SPO ), .S(A), .Y(SPO));
+ \$__ABC9_LUT7 dpo (.A(\$DPO ), .S(A), .Y(DPO));
+ \$__ABC9_LUT7 spo (.A(\$SPO ), .S(A), .Y(SPO));
endmodule
module SRL16E (
@@ -101,7 +101,7 @@
.Q(\$Q ),
.A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D)
);
- \$__ABC_LUT6 q (.A(\$Q ), .S({1'b1, A0, A1, A2, A3, 1'b1}), .Y(Q));
+ \$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A0, A1, A2, A3, 1'b1}), .Y(Q));
endmodule
module SRLC32E (
@@ -119,7 +119,7 @@
.Q(\$Q ), .Q31(Q31),
.A(A), .CE(CE), .CLK(CLK), .D(D)
);
- \$__ABC_LUT6 q (.A(\$Q ), .S({1'b1, A}), .Y(Q));
+ \$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A}), .Y(Q));
endmodule
module DSP48E1 (
@@ -308,15 +308,15 @@
if (AREG == 0 && MREG == 0 && PREG == 0)
assign iA = A, pA = 1'bx;
else
- \$__ABC_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
+ \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
if (BREG == 0 && MREG == 0 && PREG == 0)
assign iB = B, pB = 1'bx;
else
- \$__ABC_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
+ \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
if (CREG == 0 && PREG == 0)
assign iC = C, pC = 1'bx;
else
- \$__ABC_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
+ \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
if (DREG == 0)
assign iD = D;
else if (techmap_guard)
@@ -327,27 +327,27 @@
assign pAD = 1'bx;
if (PREG == 0) begin
if (MREG == 1)
- \$__ABC_REG rM (.Q(pM));
+ \$__ABC9_REG rM (.Q(pM));
else
assign pM = 1'bx;
assign pP = 1'bx;
end else begin
assign pM = 1'bx;
- \$__ABC_REG rP (.Q(pP));
+ \$__ABC9_REG rP (.Q(pP));
end
if (MREG == 0 && PREG == 0)
assign mP = oP, mPCOUT = oPCOUT;
else
assign mP = 1'bx, mPCOUT = 1'bx;
- \$__ABC_DSP48E1_MULT_P_MUX muxP (
+ \$__ABC9_DSP48E1_MULT_P_MUX muxP (
.Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
);
- \$__ABC_DSP48E1_MULT_PCOUT_MUX muxPCOUT (
+ \$__ABC9_DSP48E1_MULT_PCOUT_MUX muxPCOUT (
.Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
);
- `DSP48E1_INST(\$__ABC_DSP48E1_MULT )
+ `DSP48E1_INST(\$__ABC9_DSP48E1_MULT )
end
else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin
// Disconnect the A-input if MREG is enabled, since
@@ -355,26 +355,26 @@
if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0)
assign iA = A, pA = 1'bx;
else
- \$__ABC_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
+ \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
if (BREG == 0 && MREG == 0 && PREG == 0)
assign iB = B, pB = 1'bx;
else
- \$__ABC_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
+ \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
if (CREG == 0 && PREG == 0)
assign iC = C, pC = 1'bx;
else
- \$__ABC_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
+ \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
if (DREG == 0 && ADREG == 0)
assign iD = D, pD = 1'bx;
else
- \$__ABC_REG #(.WIDTH(25)) rD (.I(D), .O(iD), .Q(pD));
+ \$__ABC9_REG #(.WIDTH(25)) rD (.I(D), .O(iD), .Q(pD));
if (PREG == 0) begin
if (MREG == 1) begin
assign pAD = 1'bx;
- \$__ABC_REG rM (.Q(pM));
+ \$__ABC9_REG rM (.Q(pM));
end else begin
if (ADREG == 1)
- \$__ABC_REG rAD (.Q(pAD));
+ \$__ABC9_REG rAD (.Q(pAD));
else
assign pAD = 1'bx;
assign pM = 1'bx;
@@ -382,21 +382,21 @@
assign pP = 1'bx;
end else begin
assign pAD = 1'bx, pM = 1'bx;
- \$__ABC_REG rP (.Q(pP));
+ \$__ABC9_REG rP (.Q(pP));
end
if (MREG == 0 && PREG == 0)
assign mP = oP, mPCOUT = oPCOUT;
else
assign mP = 1'bx, mPCOUT = 1'bx;
- \$__ABC_DSP48E1_MULT_DPORT_P_MUX muxP (
+ \$__ABC9_DSP48E1_MULT_DPORT_P_MUX muxP (
.Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
);
- \$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX muxPCOUT (
+ \$__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX muxPCOUT (
.Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
);
- `DSP48E1_INST(\$__ABC_DSP48E1_MULT_DPORT )
+ `DSP48E1_INST(\$__ABC9_DSP48E1_MULT_DPORT )
end
else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin
// Disconnect the A-input if MREG is enabled, since
@@ -404,15 +404,15 @@
if (AREG == 0 && PREG == 0)
assign iA = A, pA = 1'bx;
else
- \$__ABC_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
+ \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
if (BREG == 0 && PREG == 0)
assign iB = B, pB = 1'bx;
else
- \$__ABC_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
+ \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
if (CREG == 0 && PREG == 0)
assign iC = C, pC = 1'bx;
else
- \$__ABC_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
+ \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
if (DREG == 1 && techmap_guard)
$error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\"");
assign pD = 1'bx;
@@ -423,7 +423,7 @@
$error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\"");
assign pM = 1'bx;
if (PREG == 1)
- \$__ABC_REG rP (.Q(pP));
+ \$__ABC9_REG rP (.Q(pP));
else
assign pP = 1'bx;
@@ -431,14 +431,14 @@
assign mP = oP, mPCOUT = oPCOUT;
else
assign mP = 1'bx, mPCOUT = 1'bx;
- \$__ABC_DSP48E1_P_MUX muxP (
+ \$__ABC9_DSP48E1_P_MUX muxP (
.Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
);
- \$__ABC_DSP48E1_PCOUT_MUX muxPCOUT (
+ \$__ABC9_DSP48E1_PCOUT_MUX muxPCOUT (
.Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
);
- `DSP48E1_INST(\$__ABC_DSP48E1 )
+ `DSP48E1_INST(\$__ABC9_DSP48E1 )
end
else
$error("Invalid DSP48E1 configuration");
diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc9_model.v
similarity index 83%
rename from techlibs/xilinx/abc_model.v
rename to techlibs/xilinx/abc9_model.v
index f19235a..8c8e155 100644
--- a/techlibs/xilinx/abc_model.v
+++ b/techlibs/xilinx/abc9_model.v
@@ -24,7 +24,7 @@
// Necessary to make these an atomic unit so that
// ABC cannot optimise just one of the MUXF7 away
// and expect to save on its delay
-(* abc_box_id = 3, lib_whitebox *)
+(* abc9_box_id = 3, lib_whitebox *)
module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1);
assign O = S1 ? (S0 ? I3 : I2)
: (S0 ? I1 : I0);
@@ -36,32 +36,32 @@
// is only committed on the next clock edge).
// To model the combinatorial path, such cells have to be split
// into comb and seq parts, with this box modelling only the former.
-(* abc_box_id=2000 *)
-module \$__ABC_LUT6 (input A, input [5:0] S, output Y);
+(* abc9_box_id=2000 *)
+module \$__ABC9_LUT6 (input A, input [5:0] S, output Y);
endmodule
// Box to emulate comb/seq behaviour of RAMD128
-(* abc_box_id=2001 *)
-module \$__ABC_LUT7 (input A, input [6:0] S, output Y);
+(* abc9_box_id=2001 *)
+module \$__ABC9_LUT7 (input A, input [6:0] S, output Y);
endmodule
// Modules used to model the comb/seq behaviour of DSP48E1
-// With abc_map.v responsible for splicing the below modules
+// With abc9_map.v responsible for splicing the below modules
// between the combinatorial DSP48E1 box (e.g. disconnecting
// A when AREG, MREG or PREG is enabled and splicing in the
-// "$__ABC_DSP48E1_REG" blackbox as "REG" in the diagram below)
+// "$__ABC9_DSP48E1_REG" blackbox as "REG" in the diagram below)
// this acts to first disables the combinatorial path (as there
// is no connectivity through REG), and secondly, since this is
// blackbox a new PI will be introduced with an arrival time of
// zero.
-// Note: Since these "$__ABC_DSP48E1_REG" modules are of a
+// Note: Since these "$__ABC9_DSP48E1_REG" modules are of a
// sequential nature, they are not passed as a box to ABC and
// (desirably) represented as PO/PIs.
//
// At the DSP output, we place a blackbox mux ("M" in the diagram
// below) to capture the fact that the critical-path could come
// from any one of its inputs.
-// In contrast to "REG", the "$__ABC_DSP48E1_*_MUX" modules are
+// In contrast to "REG", the "$__ABC9_DSP48E1_*_MUX" modules are
// combinatorial blackboxes that do get passed to ABC.
// The propagation delay through this box (specified in the box
// file) captures the arrival time of the register (i.e.
@@ -90,18 +90,18 @@
// B >>------| |
// +---------+
//
-`define ABC_DSP48E1_MUX(__NAME__) """
+`define ABC9_DSP48E1_MUX(__NAME__) """
module __NAME__ (input Aq, ADq, Bq, Cq, Dq, input [47:0] I, input Mq, input [47:0] P, input Pq, output [47:0] O);
endmodule
"""
-(* abc_box_id=2100 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_P_MUX )
-(* abc_box_id=2101 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_PCOUT_MUX )
-(* abc_box_id=2102 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_DPORT_P_MUX )
-(* abc_box_id=2103 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX )
-(* abc_box_id=2104 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_P_MUX )
-(* abc_box_id=2105 *) `ABC_DSP48E1_MUX(\$__ABC_DSP48E1_PCOUT_MUX )
+(* abc9_box_id=2100 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_MULT_P_MUX )
+(* abc9_box_id=2101 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_MULT_PCOUT_MUX )
+(* abc9_box_id=2102 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_MULT_DPORT_P_MUX )
+(* abc9_box_id=2103 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX )
+(* abc9_box_id=2104 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_P_MUX )
+(* abc9_box_id=2105 *) `ABC9_DSP48E1_MUX(\$__ABC9_DSP48E1_PCOUT_MUX )
-`define ABC_DSP48E1(__NAME__) """
+`define ABC9_DSP48E1(__NAME__) """
module __NAME__ (
output [29:0] ACOUT,
output [17:0] BCOUT,
@@ -185,6 +185,6 @@
parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
endmodule
"""
-(* abc_box_id=3000 *) `ABC_DSP48E1(\$__ABC_DSP48E1_MULT )
-(* abc_box_id=3001 *) `ABC_DSP48E1(\$__ABC_DSP48E1_MULT_DPORT )
-(* abc_box_id=3002 *) `ABC_DSP48E1(\$__ABC_DSP48E1 )
+(* abc9_box_id=3000 *) `ABC9_DSP48E1(\$__ABC9_DSP48E1_MULT )
+(* abc9_box_id=3001 *) `ABC9_DSP48E1(\$__ABC9_DSP48E1_MULT_DPORT )
+(* abc9_box_id=3002 *) `ABC9_DSP48E1(\$__ABC9_DSP48E1 )
diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc9_unmap.v
similarity index 92%
rename from techlibs/xilinx/abc_unmap.v
rename to techlibs/xilinx/abc9_unmap.v
index 8bd0579..ad64697 100644
--- a/techlibs/xilinx/abc_unmap.v
+++ b/techlibs/xilinx/abc9_unmap.v
@@ -20,19 +20,19 @@
// ============================================================================
-module \$__ABC_LUT6 (input A, input [5:0] S, output Y);
+module \$__ABC9_LUT6 (input A, input [5:0] S, output Y);
assign Y = A;
endmodule
-module \$__ABC_LUT7 (input A, input [6:0] S, output Y);
+module \$__ABC9_LUT7 (input A, input [6:0] S, output Y);
assign Y = A;
endmodule
-module \$__ABC_REG (input [WIDTH-1:0] I, output [WIDTH-1:0] O, output Q);
+module \$__ABC9_REG (input [WIDTH-1:0] I, output [WIDTH-1:0] O, output Q);
parameter WIDTH = 1;
assign O = I;
endmodule
-(* techmap_celltype = "$__ABC_DSP48E1_MULT_P_MUX $__ABC_DSP48E1_MULT_PCOUT_MUX $__ABC_DSP48E1_MULT_DPORT_P_MUX $__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX $__ABC_DSP48E1_P_MUX $__ABC_DSP48E1_PCOUT_MUX" *)
-module \$__ABC_DSP48E1_MUX (
+(* techmap_celltype = "$__ABC9_DSP48E1_MULT_P_MUX $__ABC9_DSP48E1_MULT_PCOUT_MUX $__ABC9_DSP48E1_MULT_DPORT_P_MUX $__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX $__ABC9_DSP48E1_P_MUX $__ABC9_DSP48E1_PCOUT_MUX" *)
+module \$__ABC9_DSP48E1_MUX (
input Aq, Bq, Cq, Dq, ADq,
input [47:0] I,
input Mq,
@@ -43,8 +43,8 @@
assign O = I;
endmodule
-(* techmap_celltype = "$__ABC_DSP48E1_MULT $__ABC_DSP48E1_MULT_DPORT $__ABC_DSP48E1" *)
-module \$__ABC_DSP48E1 (
+(* techmap_celltype = "$__ABC9_DSP48E1_MULT $__ABC9_DSP48E1_MULT_DPORT $__ABC9_DSP48E1" *)
+module \$__ABC9_DSP48E1 (
(* techmap_autopurge *) output [29:0] ACOUT,
(* techmap_autopurge *) output [17:0] BCOUT,
(* techmap_autopurge *) output reg CARRYCASCOUT,
diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc9_xc7.box
similarity index 99%
rename from techlibs/xilinx/abc_xc7.box
rename to techlibs/xilinx/abc9_xc7.box
index 3da3d1b..774388d 100644
--- a/techlibs/xilinx/abc_xc7.box
+++ b/techlibs/xilinx/abc9_xc7.box
@@ -50,18 +50,18 @@
# into comb and seq parts, with this box modelling only the former.
# Inputs: A S0 S1 S2 S3 S4 S5
# Outputs: Y
-$__ABC_LUT6 2000 0 7 1
+$__ABC9_LUT6 2000 0 7 1
0 642 631 472 407 238 127
# SLICEM/A6LUT + F7BMUX
# Box to emulate comb/seq behaviour of RAMD128
# Inputs: A S0 S1 S2 S3 S4 S5 S6
# Outputs: DPO SPO
-$__ABC_LUT7 2001 0 8 1
+$__ABC9_LUT7 2001 0 8 1
0 1047 1036 877 812 643 532 478
# Boxes used to represent the comb/seq behaviour of DSP48E1
-# With abc_map.v responsible for disconnecting inputs to
+# With abc9_map.v responsible for disconnecting inputs to
# the combinatorial DSP48E1 model by a register (e.g.
# disconnecting A when AREG, MREG or PREG is enabled)
# this mux captures the existence of a replacement path
@@ -70,7 +70,7 @@
# the mux at zero time, the combinatorial delay through
# these muxes thus represents the clock-to-q delay at
# P/PCOUT.
-$__ABC_DSP48E1_MULT_P_MUX 2100 0 103 48
+$__ABC9_DSP48E1_MULT_P_MUX 2100 0 103 48
# A AD B C D I M P Pq
2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
@@ -120,7 +120,7 @@
2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
2952 - 2813 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
-$__ABC_DSP48E1_MULT_PCOUT_MUX 2101 0 103 48
+$__ABC9_DSP48E1_MULT_PCOUT_MUX 2101 0 103 48
# A AD B C D I M P Pq
3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435
3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435
@@ -170,7 +170,7 @@
3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435
3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435
3098 - 2960 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435
-$__ABC_DSP48E1_MULT_DPORT_P_MUX 2102 0 103 48
+$__ABC9_DSP48E1_MULT_DPORT_P_MUX 2102 0 103 48
# A AD B C D I M P Pq
3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
@@ -220,7 +220,7 @@
3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
3935 2958 2813 1687 3908 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1671 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
-$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX 2103 0 103 48
+$__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX 2103 0 103 48
# A AD B C D I M P Pq
4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435
4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435
@@ -270,7 +270,7 @@
4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435
4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435
4083 2859 2960 1835 4056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435
-$__ABC_DSP48E1_P_MUX 2104 0 103 48
+$__ABC9_DSP48E1_P_MUX 2104 0 103 48
# A AD B C D I M P Pq
1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
@@ -320,7 +320,7 @@
1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
1632 - 1616 1687 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 329
-$__ABC_DSP48E1_PCOUT_MUX 2105 0 103 48
+$__ABC9_DSP48E1_PCOUT_MUX 2105 0 103 48
# A AD B C D I M P Pq
1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435
1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435
@@ -371,7 +371,7 @@
1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435
1780 - 1765 1835 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1819 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 435
-$__ABC_DSP48E1_MULT 3000 0 263 154
+$__ABC9_DSP48E1_MULT 3000 0 263 154
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 2823 - - 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 -
@@ -635,7 +635,7 @@
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-$__ABC_DSP48E1_MULT_DPORT 3001 0 263 154
+$__ABC9_DSP48E1_MULT_DPORT 3001 0 263 154
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 3806 - - 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 3954 -
@@ -899,7 +899,7 @@
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-$__ABC_DSP48E1 3002 0 263 154
+$__ABC9_DSP48E1 3002 0 263 154
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 1523 - - 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 1671 -
diff --git a/techlibs/xilinx/abc_xc7.lut b/techlibs/xilinx/abc9_xc7.lut
similarity index 100%
rename from techlibs/xilinx/abc_xc7.lut
rename to techlibs/xilinx/abc9_xc7.lut
diff --git a/techlibs/xilinx/abc_xc7_nowide.lut b/techlibs/xilinx/abc9_xc7_nowide.lut
similarity index 100%
rename from techlibs/xilinx/abc_xc7_nowide.lut
rename to techlibs/xilinx/abc9_xc7_nowide.lut
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index 258999f..28cd208 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -184,12 +184,12 @@
assign O = S ? CI : DI;
endmodule
-(* abc_box_id = 1, lib_whitebox *)
+(* abc9_box_id = 1, lib_whitebox *)
module MUXF7(output O, input I0, I1, S);
assign O = S ? I1 : I0;
endmodule
-(* abc_box_id = 2, lib_whitebox *)
+(* abc9_box_id = 2, lib_whitebox *)
module MUXF8(output O, input I0, I1, S);
assign O = S ? I1 : I0;
endmodule
@@ -198,12 +198,12 @@
assign O = CI ^ LI;
endmodule
-(* abc_box_id = 4, lib_whitebox *)
+(* abc9_box_id = 4, lib_whitebox *)
module CARRY4(
- (* abc_carry *)
+ (* abc9_carry *)
output [3:0] CO,
output [3:0] O,
- (* abc_carry *)
+ (* abc9_carry *)
input CI,
input CYINIT,
input [3:0] DI, S
@@ -241,7 +241,7 @@
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L238-L250
module FDRE (
- (* abc_arrival=303 *)
+ (* abc9_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
(* invertible_pin = "IS_C_INVERTED" *)
@@ -264,7 +264,7 @@
endmodule
module FDSE (
- (* abc_arrival=303 *)
+ (* abc9_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
(* invertible_pin = "IS_C_INVERTED" *)
@@ -287,7 +287,7 @@
endmodule
module FDCE (
- (* abc_arrival=303 *)
+ (* abc9_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
(* invertible_pin = "IS_C_INVERTED" *)
@@ -312,7 +312,7 @@
endmodule
module FDPE (
- (* abc_arrival=303 *)
+ (* abc9_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
(* invertible_pin = "IS_C_INVERTED" *)
@@ -337,7 +337,7 @@
endmodule
module FDRE_1 (
- (* abc_arrival=303 *)
+ (* abc9_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
input C,
@@ -349,7 +349,7 @@
endmodule
module FDSE_1 (
- (* abc_arrival=303 *)
+ (* abc9_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
input C,
@@ -361,7 +361,7 @@
endmodule
module FDCE_1 (
- (* abc_arrival=303 *)
+ (* abc9_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
input C,
@@ -373,7 +373,7 @@
endmodule
module FDPE_1 (
- (* abc_arrival=303 *)
+ (* abc9_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
input C,
@@ -430,7 +430,7 @@
module RAM32X1D (
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
- (* abc_arrival=1153 *)
+ (* abc9_arrival=1153 *)
output DPO, SPO,
input D,
(* clkbuf_sink *)
@@ -453,7 +453,7 @@
module RAM64X1D (
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
- (* abc_arrival=1153 *)
+ (* abc9_arrival=1153 *)
output DPO, SPO,
input D,
(* clkbuf_sink *)
@@ -476,7 +476,7 @@
module RAM128X1D (
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
- (* abc_arrival=1153 *)
+ (* abc9_arrival=1153 *)
output DPO, SPO,
input D,
(* clkbuf_sink *)
@@ -496,7 +496,7 @@
module SRL16E (
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905
- (* abc_arrival=1472 *)
+ (* abc9_arrival=1472 *)
output Q,
input A0, A1, A2, A3, CE,
(* clkbuf_sink *)
@@ -544,9 +544,9 @@
module SRLC32E (
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905
- (* abc_arrival=1472 *)
+ (* abc9_arrival=1472 *)
output Q,
- (* abc_arrival=1114 *)
+ (* abc9_arrival=1114 *)
output Q31,
input [4:0] A,
input CE,
diff --git a/techlibs/xilinx/cells_xtra.py b/techlibs/xilinx/cells_xtra.py
index 13dbc0e..ee20ae9 100644
--- a/techlibs/xilinx/cells_xtra.py
+++ b/techlibs/xilinx/cells_xtra.py
@@ -137,7 +137,7 @@
Cell('SYSMON'),
# Arithmetic functions.
- Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}),
+ #Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}),
# Clock components.
# Cell('BUFG', port_attrs={'O': ['clkbuf_driver']}),
@@ -264,7 +264,7 @@
Cell('XADC'),
# Arithmetic functions.
- Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}),
+ #Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}),
# Clock components.
# Cell('BUFG', port_attrs={'O': ['clkbuf_driver']}),
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index 7085214..f137408 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -339,13 +339,17 @@
run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6");
}
- if (check_label("map_dsp"), "(skip if '-nodsp')") {
+ if (check_label("map_dsp", "(skip if '-nodsp')")) {
if (!nodsp || help_mode) {
// NB: Xilinx multipliers are signed only
- run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 "
- "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
- "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
- "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18");
+ run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 "
+ "-D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 " // Partial multipliers are intentionally
+ // limited to 18x18 in order to take
+ // advantage of the (PCOUT << 17) -> PCIN
+ // dedicated cascade chain capability
+ "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
+ "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
+ "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18");
run("select a:mul2dsp");
run("setattr -unset mul2dsp");
run("opt_expr -fine");
@@ -474,13 +478,18 @@
run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut'; option for '-retime')");
else if (abc9) {
if (family != "xc7")
- log_warning("'synth_xilinx -abc9' currently supports '-family xc7' only.\n");
- run("techmap -map +/xilinx/abc_map.v -max_iter 1");
- run("read_verilog -icells -lib +/xilinx/abc_model.v");
+ log_warning("'synth_xilinx -abc9' not currently supported for the '%s' family, "
+ "will use timing for 'xc7' instead.\n", family.c_str());
+ run("techmap -map +/xilinx/abc9_map.v -max_iter 1");
+ run("read_verilog -icells -lib +/xilinx/abc9_model.v");
+ std::string abc9_opts = " -box +/xilinx/abc9_xc7.box";
+ abc9_opts += stringf(" -W %d", XC7_WIRE_DELAY);
+ abc9_opts += " -nomfs";
if (nowidelut)
- run("abc9 -lut +/xilinx/abc_xc7_nowide.lut -box +/xilinx/abc_xc7.box -W " + std::to_string(XC7_WIRE_DELAY));
+ abc9_opts += " -lut +/xilinx/abc9_xc7_nowide.lut";
else
- run("abc9 -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + std::to_string(XC7_WIRE_DELAY));
+ abc9_opts += " -lut +/xilinx/abc9_xc7.lut";
+ run("abc9" + abc9_opts);
}
else {
if (nowidelut)
@@ -498,7 +507,7 @@
if (help_mode)
techmap_args += " [-map " + ff_map_file + "]";
else if (abc9)
- techmap_args += " -map +/xilinx/abc_unmap.v";
+ techmap_args += " -map +/xilinx/abc9_unmap.v";
else
techmap_args += " -map " + ff_map_file;
run("techmap " + techmap_args);
diff --git a/techlibs/xilinx/xc6s_brams_bb.v b/techlibs/xilinx/xc6s_brams_bb.v
index 041d6b5..3c323a9 100644
--- a/techlibs/xilinx/xc6s_brams_bb.v
+++ b/techlibs/xilinx/xc6s_brams_bb.v
@@ -19,9 +19,13 @@
input [1:0] WEAWEL,
input [1:0] WEBWEU,
+ /* (* abc9_arrival=<TODO> *) */
output [15:0] DOADO,
+ /* (* abc9_arrival=<TODO> *) */
output [15:0] DOBDO,
+ /* (* abc9_arrival=<TODO> *) */
output [1:0] DOPADOP,
+ /* (* abc9_arrival=<TODO> *) */
output [1:0] DOPBDOP
);
parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
@@ -109,9 +113,13 @@
input [3:0] WEA,
input [3:0] WEB,
+ /* (* abc9_arrival=<TODO> *) */
output [31:0] DOA,
+ /* (* abc9_arrival=<TODO> *) */
output [31:0] DOB,
+ /* (* abc9_arrival=<TODO> *) */
output [3:0] DOPA,
+ /* (* abc9_arrival=<TODO> *) */
output [3:0] DOPB
);
parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
diff --git a/techlibs/xilinx/xc6v_cells_xtra.v b/techlibs/xilinx/xc6v_cells_xtra.v
index b228e40..d9e06ea 100644
--- a/techlibs/xilinx/xc6v_cells_xtra.v
+++ b/techlibs/xilinx/xc6v_cells_xtra.v
@@ -647,94 +647,6 @@
input [6:0] DADDR;
endmodule
-module DSP48E1 (...);
- parameter integer ACASCREG = 1;
- parameter integer ADREG = 1;
- parameter integer ALUMODEREG = 1;
- parameter integer AREG = 1;
- parameter AUTORESET_PATDET = "NO_RESET";
- parameter A_INPUT = "DIRECT";
- parameter integer BCASCREG = 1;
- parameter integer BREG = 1;
- parameter B_INPUT = "DIRECT";
- parameter integer CARRYINREG = 1;
- parameter integer CARRYINSELREG = 1;
- parameter integer CREG = 1;
- parameter integer DREG = 1;
- parameter integer INMODEREG = 1;
- parameter integer MREG = 1;
- parameter integer OPMODEREG = 1;
- parameter integer PREG = 1;
- parameter SEL_MASK = "MASK";
- parameter SEL_PATTERN = "PATTERN";
- parameter USE_DPORT = "FALSE";
- parameter USE_MULT = "MULTIPLY";
- parameter USE_PATTERN_DETECT = "NO_PATDET";
- parameter USE_SIMD = "ONE48";
- parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
- parameter [47:0] PATTERN = 48'h000000000000;
- parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
- parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
- parameter [0:0] IS_CLK_INVERTED = 1'b0;
- parameter [4:0] IS_INMODE_INVERTED = 5'b0;
- parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
- output [29:0] ACOUT;
- output [17:0] BCOUT;
- output CARRYCASCOUT;
- output [3:0] CARRYOUT;
- output MULTSIGNOUT;
- output OVERFLOW;
- output [47:0] P;
- output PATTERNBDETECT;
- output PATTERNDETECT;
- output [47:0] PCOUT;
- output UNDERFLOW;
- input [29:0] A;
- input [29:0] ACIN;
- (* invertible_pin = "IS_ALUMODE_INVERTED" *)
- input [3:0] ALUMODE;
- input [17:0] B;
- input [17:0] BCIN;
- input [47:0] C;
- input CARRYCASCIN;
- (* invertible_pin = "IS_CARRYIN_INVERTED" *)
- input CARRYIN;
- input [2:0] CARRYINSEL;
- input CEA1;
- input CEA2;
- input CEAD;
- input CEALUMODE;
- input CEB1;
- input CEB2;
- input CEC;
- input CECARRYIN;
- input CECTRL;
- input CED;
- input CEINMODE;
- input CEM;
- input CEP;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_CLK_INVERTED" *)
- input CLK;
- input [24:0] D;
- (* invertible_pin = "IS_INMODE_INVERTED" *)
- input [4:0] INMODE;
- input MULTSIGNIN;
- (* invertible_pin = "IS_OPMODE_INVERTED" *)
- input [6:0] OPMODE;
- input [47:0] PCIN;
- input RSTA;
- input RSTALLCARRYIN;
- input RSTALUMODE;
- input RSTB;
- input RSTC;
- input RSTCTRL;
- input RSTD;
- input RSTINMODE;
- input RSTM;
- input RSTP;
-endmodule
-
module BUFGCE (...);
parameter CE_TYPE = "SYNC";
parameter [0:0] IS_CE_INVERTED = 1'b0;
diff --git a/techlibs/xilinx/xc7_brams_bb.v b/techlibs/xilinx/xc7_brams_bb.v
index a28ba5b..c374f26 100644
--- a/techlibs/xilinx/xc7_brams_bb.v
+++ b/techlibs/xilinx/xc7_brams_bb.v
@@ -31,13 +31,13 @@
input [1:0] WEA,
input [3:0] WEBWE,
- (* abc_arrival=2454 *)
+ (* abc9_arrival=2454 *)
output [15:0] DOADO,
- (* abc_arrival=2454 *)
+ (* abc9_arrival=2454 *)
output [15:0] DOBDO,
- (* abc_arrival=2454 *)
+ (* abc9_arrival=2454 *)
output [1:0] DOPADOP,
- (* abc_arrival=2454 *)
+ (* abc9_arrival=2454 *)
output [1:0] DOPBDOP
);
parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
@@ -169,13 +169,13 @@
input [3:0] WEA,
input [7:0] WEBWE,
- (* abc_arrival=2454 *)
+ (* abc9_arrival=2454 *)
output [31:0] DOADO,
- (* abc_arrival=2454 *)
+ (* abc9_arrival=2454 *)
output [31:0] DOBDO,
- (* abc_arrival=2454 *)
+ (* abc9_arrival=2454 *)
output [3:0] DOPADOP,
- (* abc_arrival=2454 *)
+ (* abc9_arrival=2454 *)
output [3:0] DOPBDOP
);
parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
diff --git a/techlibs/xilinx/xc7_cells_xtra.v b/techlibs/xilinx/xc7_cells_xtra.v
index 0d16f81..f36e4ba 100644
--- a/techlibs/xilinx/xc7_cells_xtra.v
+++ b/techlibs/xilinx/xc7_cells_xtra.v
@@ -3376,94 +3376,6 @@
input [6:0] DADDR;
endmodule
-module DSP48E1 (...);
- parameter integer ACASCREG = 1;
- parameter integer ADREG = 1;
- parameter integer ALUMODEREG = 1;
- parameter integer AREG = 1;
- parameter AUTORESET_PATDET = "NO_RESET";
- parameter A_INPUT = "DIRECT";
- parameter integer BCASCREG = 1;
- parameter integer BREG = 1;
- parameter B_INPUT = "DIRECT";
- parameter integer CARRYINREG = 1;
- parameter integer CARRYINSELREG = 1;
- parameter integer CREG = 1;
- parameter integer DREG = 1;
- parameter integer INMODEREG = 1;
- parameter integer MREG = 1;
- parameter integer OPMODEREG = 1;
- parameter integer PREG = 1;
- parameter SEL_MASK = "MASK";
- parameter SEL_PATTERN = "PATTERN";
- parameter USE_DPORT = "FALSE";
- parameter USE_MULT = "MULTIPLY";
- parameter USE_PATTERN_DETECT = "NO_PATDET";
- parameter USE_SIMD = "ONE48";
- parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
- parameter [47:0] PATTERN = 48'h000000000000;
- parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
- parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
- parameter [0:0] IS_CLK_INVERTED = 1'b0;
- parameter [4:0] IS_INMODE_INVERTED = 5'b0;
- parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
- output [29:0] ACOUT;
- output [17:0] BCOUT;
- output CARRYCASCOUT;
- output [3:0] CARRYOUT;
- output MULTSIGNOUT;
- output OVERFLOW;
- output [47:0] P;
- output PATTERNBDETECT;
- output PATTERNDETECT;
- output [47:0] PCOUT;
- output UNDERFLOW;
- input [29:0] A;
- input [29:0] ACIN;
- (* invertible_pin = "IS_ALUMODE_INVERTED" *)
- input [3:0] ALUMODE;
- input [17:0] B;
- input [17:0] BCIN;
- input [47:0] C;
- input CARRYCASCIN;
- (* invertible_pin = "IS_CARRYIN_INVERTED" *)
- input CARRYIN;
- input [2:0] CARRYINSEL;
- input CEA1;
- input CEA2;
- input CEAD;
- input CEALUMODE;
- input CEB1;
- input CEB2;
- input CEC;
- input CECARRYIN;
- input CECTRL;
- input CED;
- input CEINMODE;
- input CEM;
- input CEP;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_CLK_INVERTED" *)
- input CLK;
- input [24:0] D;
- (* invertible_pin = "IS_INMODE_INVERTED" *)
- input [4:0] INMODE;
- input MULTSIGNIN;
- (* invertible_pin = "IS_OPMODE_INVERTED" *)
- input [6:0] OPMODE;
- input [47:0] PCIN;
- input RSTA;
- input RSTALLCARRYIN;
- input RSTALUMODE;
- input RSTB;
- input RSTC;
- input RSTCTRL;
- input RSTD;
- input RSTINMODE;
- input RSTM;
- input RSTP;
-endmodule
-
module BUFGCE (...);
parameter CE_TYPE = "SYNC";
parameter [0:0] IS_CE_INVERTED = 1'b0;
diff --git a/tests/ice40/latches.ys b/tests/ice40/latches.ys
index f356255..708734e 100644
--- a/tests/ice40/latches.ys
+++ b/tests/ice40/latches.ys
@@ -1,14 +1,11 @@
read_verilog latches.v
-design -save read
proc
-async2sync # converts latches to a 'sync' variant clocked by a 'super'-clock
flatten
-synth_ice40
-equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check
-design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+# Can't run any sort of equivalence check because latches are blown to LUTs
+#equiv_opt -async2sync -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check
-design -load read
+#design -load preopt
synth_ice40
cd top
select -assert-count 4 t:SB_LUT4
diff --git a/tests/ice40/wrapcarry.ys b/tests/ice40/wrapcarry.ys
new file mode 100644
index 0000000..10c029e
--- /dev/null
+++ b/tests/ice40/wrapcarry.ys
@@ -0,0 +1,22 @@
+read_verilog <<EOT
+module top(input A, B, CI, output O, CO);
+ SB_CARRY carry (
+ .I0(A),
+ .I1(B),
+ .CI(CI),
+ .CO(CO)
+ );
+ SB_LUT4 #(
+ .LUT_INIT(16'b 0110_1001_1001_0110)
+ ) adder (
+ .I0(1'b0),
+ .I1(A),
+ .I2(B),
+ .I3(1'b0),
+ .O(O)
+ );
+endmodule
+EOT
+
+ice40_wrapcarry
+select -assert-count 1 t:$__ICE40_CARRY_WRAPPER
diff --git a/tests/techmap/aigmap.ys b/tests/techmap/aigmap.ys
new file mode 100644
index 0000000..a40aa39
--- /dev/null
+++ b/tests/techmap/aigmap.ys
@@ -0,0 +1,10 @@
+read_verilog <<EOT
+module top(input i, j, s, output o, p);
+assign o = s ? j : i;
+assign p = ~i;
+endmodule
+EOT
+
+select t:$mux
+aigmap -select
+select -assert-any %
diff --git a/tests/techmap/techmap_replace.ys b/tests/techmap/techmap_replace.ys
new file mode 100644
index 0000000..c2f42d5
--- /dev/null
+++ b/tests/techmap/techmap_replace.ys
@@ -0,0 +1,18 @@
+read_verilog <<EOT
+module sub(input i, output o, input j);
+foobar _TECHMAP_REPLACE_(i, o, j);
+wire _TECHMAP_REPLACE_.asdf = i ;
+barfoo _TECHMAP_REPLACE_.blah (i, o, j);
+endmodule
+EOT
+design -stash techmap
+
+read_verilog <<EOT
+module top(input i, output o);
+sub s0(i, o);
+endmodule
+EOT
+
+techmap -map %techmap
+select -assert-any w:s0.asdf
+select -assert-any c:s0.blah
diff --git a/tests/xilinx/latches.ys b/tests/xilinx/latches.ys
index ac11028..bd1dffd 100644
--- a/tests/xilinx/latches.ys
+++ b/tests/xilinx/latches.ys
@@ -2,9 +2,7 @@
proc
flatten
-equiv_opt -assert -run :prove -map +/xilinx/cells_sim.v synth_xilinx # equivalency check
-async2sync
-equiv_opt -assert -run prove: -map +/xilinx/cells_sim.v synth_xilinx # equivalency check
+equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check
design -load preopt
synth_xilinx