Merge branch 'master' of github.com:YosysHQ/yosys

This commit is contained in:
Eddie Hung 2019-09-06 22:52:00 -07:00
commit de8adecd39
28 changed files with 717 additions and 213 deletions

View File

@ -88,7 +88,7 @@ ifeq ($(OS), Darwin)
PLUGIN_LDFLAGS += -undefined dynamic_lookup PLUGIN_LDFLAGS += -undefined dynamic_lookup
# homebrew search paths # homebrew search paths
ifneq ($(shell command -v brew),) ifneq ($(shell :; command -v brew),)
BREW_PREFIX := $(shell brew --prefix)/opt BREW_PREFIX := $(shell brew --prefix)/opt
$(info $$BREW_PREFIX is [${BREW_PREFIX}]) $(info $$BREW_PREFIX is [${BREW_PREFIX}])
ifeq ($(ENABLE_PYOSYS),1) ifeq ($(ENABLE_PYOSYS),1)
@ -102,8 +102,8 @@ PKG_CONFIG_PATH := $(BREW_PREFIX)/tcl-tk/lib/pkgconfig:$(PKG_CONFIG_PATH)
export PATH := $(BREW_PREFIX)/bison/bin:$(BREW_PREFIX)/gettext/bin:$(BREW_PREFIX)/flex/bin:$(PATH) export PATH := $(BREW_PREFIX)/bison/bin:$(BREW_PREFIX)/gettext/bin:$(BREW_PREFIX)/flex/bin:$(PATH)
# macports search paths # macports search paths
else ifneq ($(shell command -v port),) else ifneq ($(shell :; command -v port),)
PORT_PREFIX := $(patsubst %/bin/port,%,$(shell command -v port)) PORT_PREFIX := $(patsubst %/bin/port,%,$(shell :; command -v port))
CXXFLAGS += -I$(PORT_PREFIX)/include CXXFLAGS += -I$(PORT_PREFIX)/include
LDFLAGS += -L$(PORT_PREFIX)/lib LDFLAGS += -L$(PORT_PREFIX)/lib
PKG_CONFIG_PATH := $(PORT_PREFIX)/lib/pkgconfig:$(PKG_CONFIG_PATH) PKG_CONFIG_PATH := $(PORT_PREFIX)/lib/pkgconfig:$(PKG_CONFIG_PATH)
@ -115,7 +115,7 @@ LDFLAGS += -rdynamic
LDLIBS += -lrt LDLIBS += -lrt
endif endif
YOSYS_VER := 0.9+36 YOSYS_VER := 0.9+231
GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN) GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
OBJS = kernel/version_$(GIT_REV).o OBJS = kernel/version_$(GIT_REV).o

View File

@ -332,6 +332,10 @@ Verilog Attributes and non-standard features
that represent module parameters or localparams (when the HDL front-end that represent module parameters or localparams (when the HDL front-end
is run in ``-pwires`` mode). is run in ``-pwires`` mode).
- Wires marked with the ``hierconn`` attribute are connected to wires with the
same name (format ``cell_name.identifier``) when they are imported from
sub-modules by ``flatten``.
- The ``clkbuf_driver`` attribute can be set on an output port of a blackbox - The ``clkbuf_driver`` attribute can be set on an output port of a blackbox
module to mark it as a clock buffer output, and thus prevent ``clkbufmap`` module to mark it as a clock buffer output, and thus prevent ``clkbufmap``
from inserting another clock buffer on a net driven by such output. from inserting another clock buffer on a net driven by such output.
@ -351,19 +355,16 @@ Verilog Attributes and non-standard features
blackbox or whitebox definition to a corresponding entry in a `abc9` blackbox or whitebox definition to a corresponding entry in a `abc9`
box-file. box-file.
- The port attribute ``abc_scc_break`` indicates a module input port that will
be treated as a primary output during `abc9` techmapping. Doing so eliminates
the possibility of a strongly-connected component (i.e. a combinatorial loop)
existing. Typically, this is specified for sequential inputs on otherwise
combinatorial boxes -- for example, applying ``abc_scc_break`` onto the `D`
port of a LUTRAM cell prevents `abc9` from interpreting any `Q` -> `D` paths
as a combinatorial loop.
- The port attribute ``abc_carry`` marks the carry-in (if an input port) and - The port attribute ``abc_carry`` marks the carry-in (if an input port) and
carry-out (if output port) ports of a box. This information is necessary for carry-out (if output port) ports of a box. This information is necessary for
`abc9` to preserve the integrity of carry-chains. Specifying this attribute `abc9` to preserve the integrity of carry-chains. Specifying this attribute
onto a bus port will affect only its most significant bit. onto a bus port will affect only its most significant bit.
- The port attribute ``abc_arrival`` specifies an integer (for output ports
only) to be used as the arrival time of this sequential port. It can be used,
for example, to specify the clk-to-Q delay of a flip-flop for consideration
during techmapping.
- In addition to the ``(* ... *)`` attribute syntax, Yosys supports - In addition to the ``(* ... *)`` attribute syntax, Yosys supports
the non-standard ``{* ... *}`` attribute syntax to set default attributes the non-standard ``{* ... *}`` attribute syntax to set default attributes
for everything that comes after the ``{* ... *}`` statement. (Reset for everything that comes after the ``{* ... *}`` statement. (Reset

View File

@ -83,6 +83,7 @@ struct XAigerWriter
dict<SigBit, pair<SigBit, SigBit>> and_map; dict<SigBit, pair<SigBit, SigBit>> and_map;
vector<std::tuple<SigBit,RTLIL::Cell*,RTLIL::IdString,int>> ci_bits; vector<std::tuple<SigBit,RTLIL::Cell*,RTLIL::IdString,int>> ci_bits;
vector<std::tuple<SigBit,RTLIL::Cell*,RTLIL::IdString,int,int>> co_bits; vector<std::tuple<SigBit,RTLIL::Cell*,RTLIL::IdString,int,int>> co_bits;
dict<SigBit, float> arrival_times;
vector<pair<int, int>> aig_gates; vector<pair<int, int>> aig_gates;
vector<int> aig_outputs; vector<int> aig_outputs;
@ -247,14 +248,15 @@ struct XAigerWriter
if (!holes_mode) { if (!holes_mode) {
toposort.node(cell->name); toposort.node(cell->name);
for (const auto &conn : cell->connections()) { for (const auto &conn : cell->connections()) {
if (cell->input(conn.first)) { auto port_wire = inst_module->wire(conn.first);
if (port_wire->port_input) {
// Ignore inout for the sake of topographical ordering // Ignore inout for the sake of topographical ordering
if (cell->output(conn.first)) continue; if (port_wire->port_output) continue;
for (auto bit : sigmap(conn.second)) for (auto bit : sigmap(conn.second))
bit_users[bit].insert(cell->name); bit_users[bit].insert(cell->name);
} }
if (cell->output(conn.first)) if (port_wire->port_output)
for (auto bit : sigmap(conn.second)) for (auto bit : sigmap(conn.second))
bit_drivers[bit].insert(cell->name); bit_drivers[bit].insert(cell->name);
} }
@ -271,7 +273,7 @@ struct XAigerWriter
log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type));
if (is_input) { if (is_input) {
for (auto b : c.second.bits()) { for (auto b : c.second) {
Wire *w = b.wire; Wire *w = b.wire;
if (!w) continue; if (!w) continue;
if (!w->port_output || !cell_known) { if (!w->port_output || !cell_known) {
@ -287,7 +289,17 @@ struct XAigerWriter
} }
} }
if (is_output) { if (is_output) {
for (auto b : c.second.bits()) { int arrival = 0;
if (port_wire) {
auto it = port_wire->attributes.find("\\abc_arrival");
if (it != port_wire->attributes.end()) {
if (it->second.flags != 0)
log_error("Attribute 'abc_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type));
arrival = it->second.as_int();
}
}
for (auto b : c.second) {
Wire *w = b.wire; Wire *w = b.wire;
if (!w) continue; if (!w) continue;
input_bits.insert(b); input_bits.insert(b);
@ -295,6 +307,9 @@ struct XAigerWriter
if (O != b) if (O != b)
alias_map[O] = b; alias_map[O] = b;
undriven_bits.erase(O); undriven_bits.erase(O);
if (arrival)
arrival_times[b] = arrival;
} }
} }
} }
@ -489,16 +504,16 @@ struct XAigerWriter
aig_outputs.push_back(bit2aig(bit)); aig_outputs.push_back(bit2aig(bit));
} }
if (output_bits.empty()) {
output_bits.insert(State::S0);
omode = true;
}
for (auto bit : output_bits) { for (auto bit : output_bits) {
ordered_outputs[bit] = aig_o++; ordered_outputs[bit] = aig_o++;
aig_outputs.push_back(bit2aig(bit)); aig_outputs.push_back(bit2aig(bit));
} }
if (output_bits.empty()) {
aig_o++;
aig_outputs.push_back(0);
omode = true;
}
} }
void write_aiger(std::ostream &f, bool ascii_mode) void write_aiger(std::ostream &f, bool ascii_mode)
@ -560,26 +575,38 @@ struct XAigerWriter
f << "c"; f << "c";
log_assert(!output_bits.empty());
auto write_buffer = [](std::stringstream &buffer, int i32) {
int32_t i32_be = to_big_endian(i32);
buffer.write(reinterpret_cast<const char*>(&i32_be), sizeof(i32_be));
};
std::stringstream h_buffer;
auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1);
write_h_buffer(1);
log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits));
write_h_buffer(input_bits.size() + ci_bits.size());
log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits));
write_h_buffer(output_bits.size() + GetSize(co_bits));
log_debug("piNum = %d\n", GetSize(input_bits));
write_h_buffer(input_bits.size());
log_debug("poNum = %d\n", GetSize(output_bits));
write_h_buffer(output_bits.size());
log_debug("boxNum = %d\n", GetSize(box_list));
write_h_buffer(box_list.size());
auto write_buffer_float = [](std::stringstream &buffer, float f32) {
buffer.write(reinterpret_cast<const char*>(&f32), sizeof(f32));
};
std::stringstream i_buffer;
auto write_i_buffer = std::bind(write_buffer_float, std::ref(i_buffer), std::placeholders::_1);
for (auto bit : input_bits)
write_i_buffer(arrival_times.at(bit, 0));
//std::stringstream o_buffer;
//auto write_o_buffer = std::bind(write_buffer_float, std::ref(o_buffer), std::placeholders::_1);
//for (auto bit : output_bits)
// write_o_buffer(0);
if (!box_list.empty()) { if (!box_list.empty()) {
auto write_buffer = [](std::stringstream &buffer, int i32) {
int32_t i32_be = to_big_endian(i32);
buffer.write(reinterpret_cast<const char*>(&i32_be), sizeof(i32_be));
};
std::stringstream h_buffer;
auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1);
write_h_buffer(1);
log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits));
write_h_buffer(input_bits.size() + ci_bits.size());
log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits));
write_h_buffer(output_bits.size() + co_bits.size());
log_debug("piNum = %d\n", GetSize(input_bits));
write_h_buffer(input_bits.size());
log_debug("poNum = %d\n", GetSize(output_bits));
write_h_buffer(output_bits.size());
log_debug("boxNum = %d\n", GetSize(box_list));
write_h_buffer(box_list.size());
RTLIL::Module *holes_module = module->design->addModule("$__holes__"); RTLIL::Module *holes_module = module->design->addModule("$__holes__");
log_assert(holes_module); log_assert(holes_module);
@ -643,19 +670,12 @@ struct XAigerWriter
write_h_buffer(box_count++); write_h_buffer(box_count++);
} }
f << "h";
std::string buffer_str = h_buffer.str();
int32_t buffer_size_be = to_big_endian(buffer_str.size());
f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
f.write(buffer_str.data(), buffer_str.size());
std::stringstream r_buffer; std::stringstream r_buffer;
auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1);
write_r_buffer(0); write_r_buffer(0);
f << "r"; f << "r";
buffer_str = r_buffer.str(); std::string buffer_str = r_buffer.str();
buffer_size_be = to_big_endian(buffer_str.size()); int32_t buffer_size_be = to_big_endian(buffer_str.size());
f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be)); f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
f.write(buffer_str.data(), buffer_str.size()); f.write(buffer_str.data(), buffer_str.size());
@ -709,6 +729,23 @@ struct XAigerWriter
} }
} }
f << "h";
std::string buffer_str = h_buffer.str();
int32_t buffer_size_be = to_big_endian(buffer_str.size());
f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
f.write(buffer_str.data(), buffer_str.size());
f << "i";
buffer_str = i_buffer.str();
buffer_size_be = to_big_endian(buffer_str.size());
f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
f.write(buffer_str.data(), buffer_str.size());
//f << "o";
//buffer_str = o_buffer.str();
//buffer_size_be = to_big_endian(buffer_str.size());
//f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
//f.write(buffer_str.data(), buffer_str.size());
f << stringf("Generated by %s\n", yosys_version_str); f << stringf("Generated by %s\n", yosys_version_str);
} }
@ -760,11 +797,11 @@ struct XAigerWriter
f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name));
output_lines.sort(); output_lines.sort();
if (omode)
output_lines[State::S0] = "output 0 0 $__dummy__\n";
for (auto &it : output_lines) for (auto &it : output_lines)
f << it.second; f << it.second;
log_assert(output_lines.size() == output_bits.size()); log_assert(output_lines.size() == output_bits.size());
if (omode && output_bits.empty())
f << "output " << output_lines.size() << " 0 $__dummy__\n";
wire_lines.sort(); wire_lines.sort();
for (auto &it : wire_lines) for (auto &it : wire_lines)

View File

@ -430,6 +430,7 @@ void AigerReader::parse_xaiger(const dict<int,IdString> &box_lookup)
else if (c == 'r') { else if (c == 'r') {
uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
flopNum = parse_xaiger_literal(f); flopNum = parse_xaiger_literal(f);
log_debug("flopNum: %u\n", flopNum);
log_assert(dataSize == (flopNum+1) * sizeof(uint32_t)); log_assert(dataSize == (flopNum+1) * sizeof(uint32_t));
f.ignore(flopNum * sizeof(uint32_t)); f.ignore(flopNum * sizeof(uint32_t));
} }
@ -496,8 +497,7 @@ void AigerReader::parse_aiger_ascii()
// Parse latches // Parse latches
RTLIL::Wire *clk_wire = nullptr; RTLIL::Wire *clk_wire = nullptr;
if (L > 0) { if (L > 0 && !clk_name.empty()) {
log_assert(clk_name != "");
clk_wire = module->wire(clk_name); clk_wire = module->wire(clk_name);
log_assert(!clk_wire); log_assert(!clk_wire);
log_debug2("Creating %s\n", clk_name.c_str()); log_debug2("Creating %s\n", clk_name.c_str());
@ -513,7 +513,10 @@ void AigerReader::parse_aiger_ascii()
RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); RTLIL::Wire *q_wire = createWireIfNotExists(module, l1);
RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); RTLIL::Wire *d_wire = createWireIfNotExists(module, l2);
module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire); if (clk_wire)
module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire);
else
module->addFfGate(NEW_ID, d_wire, q_wire);
// Reset logic is optional in AIGER 1.9 // Reset logic is optional in AIGER 1.9
if (f.peek() == ' ') { if (f.peek() == ' ') {
@ -621,8 +624,7 @@ void AigerReader::parse_aiger_binary()
// Parse latches // Parse latches
RTLIL::Wire *clk_wire = nullptr; RTLIL::Wire *clk_wire = nullptr;
if (L > 0) { if (L > 0 && !clk_name.empty()) {
log_assert(clk_name != "");
clk_wire = module->wire(clk_name); clk_wire = module->wire(clk_name);
log_assert(!clk_wire); log_assert(!clk_wire);
log_debug2("Creating %s\n", clk_name.c_str()); log_debug2("Creating %s\n", clk_name.c_str());
@ -638,7 +640,10 @@ void AigerReader::parse_aiger_binary()
RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); RTLIL::Wire *q_wire = createWireIfNotExists(module, l1);
RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); RTLIL::Wire *d_wire = createWireIfNotExists(module, l2);
module->addDff(NEW_ID, clk_wire, d_wire, q_wire); if (clk_wire)
module->addDff(NEW_ID, clk_wire, d_wire, q_wire);
else
module->addFf(NEW_ID, d_wire, q_wire);
// Reset logic is optional in AIGER 1.9 // Reset logic is optional in AIGER 1.9
if (f.peek() == ' ') { if (f.peek() == ' ') {
@ -776,19 +781,19 @@ void AigerReader::post_process()
// NB: Assume box_module->ports are sorted alphabetically // NB: Assume box_module->ports are sorted alphabetically
// (as RTLIL::Module::fixup_ports() would do) // (as RTLIL::Module::fixup_ports() would do)
for (auto port_name : box_module->ports) { for (auto port_name : box_module->ports) {
RTLIL::Wire* w = box_module->wire(port_name); RTLIL::Wire* port = box_module->wire(port_name);
log_assert(w); log_assert(port);
RTLIL::SigSpec rhs; RTLIL::SigSpec rhs;
RTLIL::Wire* wire = nullptr; for (int i = 0; i < GetSize(port); i++) {
for (int i = 0; i < GetSize(w); i++) { RTLIL::Wire* wire = nullptr;
if (w->port_input) { if (port->port_input) {
log_assert(co_count < outputs.size()); log_assert(co_count < outputs.size());
wire = outputs[co_count++]; wire = outputs[co_count++];
log_assert(wire); log_assert(wire);
log_assert(wire->port_output); log_assert(wire->port_output);
wire->port_output = false; wire->port_output = false;
} }
if (w->port_output) { if (port->port_output) {
log_assert((piNum + ci_count) < inputs.size()); log_assert((piNum + ci_count) < inputs.size());
wire = inputs[piNum + ci_count++]; wire = inputs[piNum + ci_count++];
log_assert(wire); log_assert(wire);
@ -797,6 +802,7 @@ void AigerReader::post_process()
} }
rhs.append(wire); rhs.append(wire);
} }
cell->setPort(port_name, rhs); cell->setPort(port_name, rhs);
} }
} }
@ -814,6 +820,7 @@ void AigerReader::post_process()
RTLIL::Wire* wire = inputs[variable]; RTLIL::Wire* wire = inputs[variable];
log_assert(wire); log_assert(wire);
log_assert(wire->port_input); log_assert(wire->port_input);
log_debug("Renaming input %s", log_id(wire));
if (index == 0) { if (index == 0) {
// Cope with the fact that a CI might be identical // Cope with the fact that a CI might be identical
@ -840,6 +847,7 @@ void AigerReader::post_process()
wire->port_input = false; wire->port_input = false;
} }
} }
log_debug(" -> %s\n", log_id(wire));
} }
else if (type == "output") { else if (type == "output") {
log_assert(static_cast<unsigned>(variable + co_count) < outputs.size()); log_assert(static_cast<unsigned>(variable + co_count) < outputs.size());
@ -850,6 +858,7 @@ void AigerReader::post_process()
wire->port_output = false; wire->port_output = false;
continue; continue;
} }
log_debug("Renaming output %s", log_id(wire));
if (index == 0) { if (index == 0) {
// Cope with the fact that a CO might be identical // Cope with the fact that a CO might be identical
@ -871,6 +880,7 @@ void AigerReader::post_process()
else { else {
wire->port_output = false; wire->port_output = false;
module->connect(wire, existing); module->connect(wire, existing);
wire = existing;
} }
} }
else if (index > 0) { else if (index > 0) {
@ -896,6 +906,7 @@ void AigerReader::post_process()
wire->port_output = false; wire->port_output = false;
} }
} }
log_debug(" -> %s\n", log_id(wire));
} }
else if (type == "box") { else if (type == "box") {
RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable)); RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable));
@ -1004,8 +1015,8 @@ struct AigerFrontend : public Frontend {
log(" Name of module to be created (default: <filename>)\n"); log(" Name of module to be created (default: <filename>)\n");
log("\n"); log("\n");
log(" -clk_name <wire_name>\n"); log(" -clk_name <wire_name>\n");
log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); log(" If specified, AIGER latches to be transformed into $_DFF_P_ cells\n");
log(" this name (default: clk)\n"); log(" clocked by wire of this name. Otherwise, $_FF_ cells will be used.\n");
log("\n"); log("\n");
log(" -map <filename>\n"); log(" -map <filename>\n");
log(" read file with port and latch symbols\n"); log(" read file with port and latch symbols\n");

View File

@ -1530,10 +1530,16 @@ skip_dynamic_range_lvalue_expansion:;
current_scope[wire_en->str] = wire_en; current_scope[wire_en->str] = wire_en;
while (wire_en->simplify(true, false, false, 1, -1, false, false)) { } while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
std::vector<RTLIL::State> x_bit; AstNode *check_defval;
x_bit.push_back(RTLIL::State::Sx); if (type == AST_LIVE || type == AST_FAIR) {
check_defval = new AstNode(AST_REDUCE_BOOL, children[0]->clone());
} else {
std::vector<RTLIL::State> x_bit;
x_bit.push_back(RTLIL::State::Sx);
check_defval = mkconst_bits(x_bit, false);
}
AstNode *assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bit, false)); AstNode *assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), check_defval);
assign_check->children[0]->str = id_check; assign_check->children[0]->str = id_check;
assign_check->children[0]->was_checked = true; assign_check->children[0]->was_checked = true;
@ -1546,9 +1552,13 @@ skip_dynamic_range_lvalue_expansion:;
default_signals->children.push_back(assign_en); default_signals->children.push_back(assign_en);
current_top_block->children.insert(current_top_block->children.begin(), default_signals); current_top_block->children.insert(current_top_block->children.begin(), default_signals);
assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_REDUCE_BOOL, children[0]->clone())); if (type == AST_LIVE || type == AST_FAIR) {
assign_check->children[0]->str = id_check; assign_check = nullptr;
assign_check->children[0]->was_checked = true; } else {
assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_REDUCE_BOOL, children[0]->clone()));
assign_check->children[0]->str = id_check;
assign_check->children[0]->was_checked = true;
}
if (current_always == nullptr || current_always->type != AST_INITIAL) { if (current_always == nullptr || current_always->type != AST_INITIAL) {
assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(1, false, 1)); assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(1, false, 1));
@ -1560,7 +1570,8 @@ skip_dynamic_range_lvalue_expansion:;
assign_en->children[0]->was_checked = true; assign_en->children[0]->was_checked = true;
newNode = new AstNode(AST_BLOCK); newNode = new AstNode(AST_BLOCK);
newNode->children.push_back(assign_check); if (assign_check != nullptr)
newNode->children.push_back(assign_check);
newNode->children.push_back(assign_en); newNode->children.push_back(assign_en);
AstNode *assertnode = new AstNode(type); AstNode *assertnode = new AstNode(type);

View File

@ -76,8 +76,7 @@ inline std::string remap_name(RTLIL::IdString abc_name)
return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1); return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1);
} }
void handle_loops(RTLIL::Design *design, void handle_loops(RTLIL::Design *design)
const dict<IdString,pool<IdString>> &scc_break_inputs)
{ {
Pass::call(design, "scc -set_attr abc_scc_id {}"); Pass::call(design, "scc -set_attr abc_scc_id {}");
@ -114,30 +113,6 @@ void handle_loops(RTLIL::Design *design,
} }
cell->attributes.erase(it); cell->attributes.erase(it);
} }
auto jt = scc_break_inputs.find(cell->type);
if (jt != scc_break_inputs.end())
for (auto port_name : jt->second) {
RTLIL::SigSpec sig;
auto &rhs = cell->connections_.at(port_name);
for (auto b : rhs) {
Wire *w = b.wire;
if (!w) continue;
w->port_output = true;
w->set_bool_attribute(ID(abc_scc_break));
w = module->wire(stringf("%s.abci", w->name.c_str()));
if (!w) {
w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire));
w->port_input = true;
}
else {
log_assert(b.offset < GetSize(w));
log_assert(w->port_input);
}
sig.append(RTLIL::SigBit(w, b.offset));
}
rhs = sig;
}
} }
module->fixup_ports(); module->fixup_ports();
@ -272,8 +247,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str, 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 /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
bool show_tempdir, std::string box_file, std::string lut_file, 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
const dict<IdString,pool<IdString>> &scc_break_inputs
) )
{ {
module = current_module; module = current_module;
@ -413,7 +387,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
RTLIL::Selection& sel = design->selection_stack.back(); RTLIL::Selection& sel = design->selection_stack.back();
sel.select(module); sel.select(module);
handle_loops(design, scc_break_inputs); handle_loops(design);
Pass::call(design, "aigmap"); Pass::call(design, "aigmap");
@ -1050,9 +1024,6 @@ struct Abc9Pass : public Pass {
} }
if (arg == "-box" && argidx+1 < args.size()) { if (arg == "-box" && argidx+1 < args.size()) {
box_file = args[++argidx]; box_file = args[++argidx];
rewrite_filename(box_file);
if (!box_file.empty() && !is_absolute_path(box_file))
box_file = std::string(pwd) + "/" + box_file;
continue; continue;
} }
if (arg == "-W" && argidx+1 < args.size()) { if (arg == "-W" && argidx+1 < args.size()) {
@ -1063,8 +1034,15 @@ struct Abc9Pass : public Pass {
} }
extra_args(args, argidx, design); extra_args(args, argidx, design);
// ABC expects a box file for XAIG
if (box_file.empty())
box_file = "+/dummy.box";
rewrite_filename(box_file);
if (!box_file.empty() && !is_absolute_path(box_file))
box_file = std::string(pwd) + "/" + box_file;
dict<int,IdString> box_lookup; dict<int,IdString> box_lookup;
dict<IdString,pool<IdString>> scc_break_inputs;
for (auto m : design->modules()) { for (auto m : design->modules()) {
auto it = m->attributes.find(ID(abc_box_id)); auto it = m->attributes.find(ID(abc_box_id));
if (it == m->attributes.end()) if (it == m->attributes.end())
@ -1082,17 +1060,13 @@ struct Abc9Pass : public Pass {
for (auto p : m->ports) { for (auto p : m->ports) {
auto w = m->wire(p); auto w = m->wire(p);
log_assert(w); log_assert(w);
if (w->port_input) { if (w->attributes.count(ID(abc_carry))) {
if (w->attributes.count(ID(abc_scc_break))) if (w->port_input) {
scc_break_inputs[m->name].insert(p);
if (w->attributes.count(ID(abc_carry))) {
if (carry_in) 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 'abc_carry' input port.\n", log_id(m));
carry_in = w; carry_in = w;
} }
} else if (w->port_output) {
if (w->port_output) {
if (w->attributes.count(ID(abc_carry))) {
if (carry_out) 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 'abc_carry' input port.\n", log_id(m));
carry_out = w; carry_out = w;
@ -1144,7 +1118,7 @@ struct Abc9Pass : public Pass {
if (!dff_mode || !clk_str.empty()) { if (!dff_mode || !clk_str.empty()) {
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff, abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
delay_target, lutin_shared, fast_mode, show_tempdir, delay_target, lutin_shared, fast_mode, show_tempdir,
box_file, lut_file, wire_delay, box_lookup, scc_break_inputs); box_file, lut_file, wire_delay, box_lookup);
continue; continue;
} }
@ -1290,7 +1264,7 @@ struct Abc9Pass : public Pass {
en_sig = assign_map(std::get<3>(it.first)); en_sig = assign_map(std::get<3>(it.first));
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$", abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$",
keepff, delay_target, lutin_shared, fast_mode, show_tempdir, keepff, delay_target, lutin_shared, fast_mode, show_tempdir,
box_file, lut_file, wire_delay, box_lookup, scc_break_inputs); box_file, lut_file, wire_delay, box_lookup);
assign_map.set(mod); assign_map.set(mod);
} }
} }

View File

@ -205,20 +205,38 @@ struct TechmapWorker
} }
std::map<RTLIL::IdString, RTLIL::IdString> positional_ports; std::map<RTLIL::IdString, RTLIL::IdString> positional_ports;
dict<Wire*, IdString> temp_renamed_wires;
for (auto &it : tpl->wires_) { for (auto &it : tpl->wires_) {
if (it.second->port_id > 0) if (it.second->port_id > 0)
positional_ports[stringf("$%d", it.second->port_id)] = it.first; positional_ports[stringf("$%d", it.second->port_id)] = it.first;
IdString w_name = it.second->name; IdString w_name = it.second->name;
apply_prefix(cell->name, w_name); apply_prefix(cell->name, w_name);
RTLIL::Wire *w = module->addWire(w_name, it.second); RTLIL::Wire *w = module->wire(w_name);
w->port_input = false; if (w != nullptr) {
w->port_output = false; if (!flatten_mode || !w->get_bool_attribute(ID(hierconn))) {
w->port_id = 0; temp_renamed_wires[w] = w->name;
if (it.second->get_bool_attribute(ID(_techmap_special_))) module->rename(w, NEW_ID);
w->attributes.clear(); w = nullptr;
if (w->attributes.count(ID(src))) } else {
w->add_strpool_attribute(ID(src), extra_src_attrs); w->attributes.erase(ID(hierconn));
if (GetSize(w) < GetSize(it.second)) {
log_warning("Widening signal %s.%s to match size of %s.%s (via %s.%s).\n", log_id(module), log_id(w),
log_id(tpl), log_id(it.second), log_id(module), log_id(cell));
w->width = GetSize(it.second);
}
}
}
if (w == nullptr) {
w = module->addWire(w_name, it.second);
w->port_input = false;
w->port_output = false;
w->port_id = 0;
if (it.second->get_bool_attribute(ID(_techmap_special_)))
w->attributes.clear();
if (w->attributes.count(ID(src)))
w->add_strpool_attribute(ID(src), extra_src_attrs);
}
design->select(module, w); design->select(module, w);
} }
@ -380,6 +398,16 @@ struct TechmapWorker
} }
module->remove(cell); module->remove(cell);
for (auto &it : temp_renamed_wires)
{
Wire *w = it.first;
IdString name = it.second;
IdString altname = module->uniquify(name);
Wire *other_w = module->wire(name);
module->rename(other_w, altname);
module->rename(w, name);
}
} }
bool techmap_module(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Design *map, std::set<RTLIL::Cell*> &handled_cells, bool techmap_module(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Design *map, std::set<RTLIL::Cell*> &handled_cells,

View File

@ -28,3 +28,4 @@ $(eval $(call add_share_file,share,techlibs/common/dff2ff.v))
$(eval $(call add_share_file,share,techlibs/common/gate2lut.v)) $(eval $(call add_share_file,share,techlibs/common/gate2lut.v))
$(eval $(call add_share_file,share,techlibs/common/cmp2lut.v)) $(eval $(call add_share_file,share,techlibs/common/cmp2lut.v))
$(eval $(call add_share_file,share,techlibs/common/cells.lib)) $(eval $(call add_share_file,share,techlibs/common/cells.lib))
$(eval $(call add_share_file,share,techlibs/common/dummy.box))

View File

@ -0,0 +1 @@
(dummy) 1 0 0 0

View File

@ -14,6 +14,9 @@ $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram.txt))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_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.box))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_5g.lut)) $(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/abc_5g_nowide.lut))

View File

@ -15,16 +15,16 @@ CCU2C 1 1 9 3
630 379 630 379 526 275 392 141 273 630 379 630 379 526 275 392 141 273
516 516 516 516 412 412 278 278 43 516 516 516 516 412 412 278 278 43
# Box 2 : TRELLIS_DPR16X4 (16x4 dist ram) # Box 2 : TRELLIS_DPR16X4_COMB (16x4 dist ram)
# Outputs: DO0, DO1, DO2, DO3 # Outputs: DO0, DO1, DO2, DO3
# name ID w/b ins outs # name ID w/b ins outs
TRELLIS_DPR16X4 2 0 14 4 $__ABC_DPR16X4_COMB 2 0 8 4
#DI0 DI1 DI2 DI3 RAD0 RAD1 RAD2 RAD3 WAD0 WAD1 WAD2 WAD3 WCK WRE #A0 A1 A2 A3 RAD0 RAD1 RAD2 RAD3
- - - - 141 379 275 379 - - - - - - 0 0 0 0 141 379 275 379
- - - - 141 379 275 379 - - - - - - 0 0 0 0 141 379 275 379
- - - - 141 379 275 379 - - - - - - 0 0 0 0 141 379 275 379
- - - - 141 379 275 379 - - - - - - 0 0 0 0 141 379 275 379
# Box 3 : PFUMX (MUX2) # Box 3 : PFUMX (MUX2)
# Outputs: Z # Outputs: Z

24
techlibs/ecp5/abc_map.v Normal file
View File

@ -0,0 +1,24 @@
// ---------------------------------------
module TRELLIS_DPR16X4 (
input [3:0] DI,
input [3:0] WAD,
input WRE,
input WCK,
input [3:0] RAD,
output [3:0] DO
);
parameter WCKMUX = "WCK";
parameter WREMUX = "WRE";
parameter [63:0] INITVAL = 64'h0000000000000000;
wire [3:0] \$DO ;
TRELLIS_DPR16X4 #(
.WCKMUX(WCKMUX), .WREMUX(WREMUX), .INITVAL(INITVAL)
) _TECHMAP_REPLACE_ (
.DI(DI), .WAD(WAD), .WRE(WRE), .WCK(WCK),
.RAD(RAD), .DO(\$DO )
);
\$__ABC_DPR16X4_COMB do (.A(\$DO ), .S(RAD), .Y(DO));
endmodule

View File

@ -0,0 +1,5 @@
// ---------------------------------------
(* abc_box_id=2 *)
module \$__ABC_DPR16X4_COMB (input [3:0] A, S, output [3:0] Y);
endmodule

View File

@ -0,0 +1,5 @@
// ---------------------------------------
module \$__ABC_DPR16X4_COMB (input [3:0] A, S, output [3:0] Y);
assign Y = A;
endmodule

View File

@ -109,16 +109,13 @@ module PFUMX (input ALUT, BLUT, C0, output Z);
endmodule endmodule
// --------------------------------------- // ---------------------------------------
//(* abc_box_id=2 *)
module TRELLIS_DPR16X4 ( module TRELLIS_DPR16X4 (
(* abc_scc_break *)
input [3:0] DI, input [3:0] DI,
(* abc_scc_break *)
input [3:0] WAD, input [3:0] WAD,
(* abc_scc_break *)
input WRE, input WRE,
input WCK, input WCK,
input [3:0] RAD, input [3:0] RAD,
/* (* abc_arrival=<TODO> *) */
output [3:0] DO output [3:0] DO
); );
parameter WCKMUX = "WCK"; parameter WCKMUX = "WCK";

View File

@ -280,12 +280,17 @@ struct SynthEcp5Pass : public ScriptPass
if (abc2 || help_mode) { if (abc2 || help_mode) {
run("abc", " (only if -abc2)"); run("abc", " (only if -abc2)");
} }
run("techmap -map +/ecp5/latches_map.v"); std::string techmap_args = "-map +/ecp5/latches_map.v";
if (abc9)
techmap_args += " -map +/ecp5/abc_map.v -max_iter 1";
run("techmap " + techmap_args);
if (abc9) { if (abc9) {
if (nowidelut) if (nowidelut)
run("abc9 -lut +/ecp5/abc_5g_nowide.lut -box +/ecp5/abc_5g.box -W 200"); run("abc9 -lut +/ecp5/abc_5g_nowide.lut -box +/ecp5/abc_5g.box -W 200");
else else
run("abc9 -lut +/ecp5/abc_5g.lut -box +/ecp5/abc_5g.box -W 200"); run("abc9 -lut +/ecp5/abc_5g.lut -box +/ecp5/abc_5g.box -W 200");
run("techmap -map +/ecp5/abc_unmap.v");
} else { } else {
if (nowidelut) if (nowidelut)
run("abc -lut 4 -dress"); run("abc -lut 4 -dress");

View File

@ -2,6 +2,10 @@
`define SB_DFF_REG reg Q = 0 `define SB_DFF_REG reg Q = 0
// `define SB_DFF_REG reg Q // `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
// SiliconBlue IO Cells // SiliconBlue IO Cells
module SB_IO ( module SB_IO (
@ -169,20 +173,42 @@ module \$__ICE40_CARRY_WRAPPER (
); );
endmodule 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
// Positive Edge SiliconBlue FF Cells // Positive Edge SiliconBlue FF Cells
module SB_DFF (output `SB_DFF_REG, input C, D); module SB_DFF (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, D
);
always @(posedge C) always @(posedge C)
Q <= D; Q <= D;
endmodule endmodule
module SB_DFFE (output `SB_DFF_REG, input C, E, D); module SB_DFFE (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, D
);
always @(posedge C) always @(posedge C)
if (E) if (E)
Q <= D; Q <= D;
endmodule endmodule
module SB_DFFSR (output `SB_DFF_REG, input C, R, D); module SB_DFFSR (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, R, D
);
always @(posedge C) always @(posedge C)
if (R) if (R)
Q <= 0; Q <= 0;
@ -190,7 +216,13 @@ module SB_DFFSR (output `SB_DFF_REG, input C, R, D);
Q <= D; Q <= D;
endmodule endmodule
module SB_DFFR (output `SB_DFF_REG, input C, R, D); module SB_DFFR (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, R, D
);
always @(posedge C, posedge R) always @(posedge C, posedge R)
if (R) if (R)
Q <= 0; Q <= 0;
@ -198,7 +230,13 @@ module SB_DFFR (output `SB_DFF_REG, input C, R, D);
Q <= D; Q <= D;
endmodule endmodule
module SB_DFFSS (output `SB_DFF_REG, input C, S, D); module SB_DFFSS (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, S, D
);
always @(posedge C) always @(posedge C)
if (S) if (S)
Q <= 1; Q <= 1;
@ -206,7 +244,13 @@ module SB_DFFSS (output `SB_DFF_REG, input C, S, D);
Q <= D; Q <= D;
endmodule endmodule
module SB_DFFS (output `SB_DFF_REG, input C, S, D); module SB_DFFS (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, S, D
);
always @(posedge C, posedge S) always @(posedge C, posedge S)
if (S) if (S)
Q <= 1; Q <= 1;
@ -214,7 +258,13 @@ module SB_DFFS (output `SB_DFF_REG, input C, S, D);
Q <= D; Q <= D;
endmodule endmodule
module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D); module SB_DFFESR (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, R, D
);
always @(posedge C) always @(posedge C)
if (E) begin if (E) begin
if (R) if (R)
@ -224,7 +274,13 @@ module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D);
end end
endmodule endmodule
module SB_DFFER (output `SB_DFF_REG, input C, E, R, D); module SB_DFFER (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, R, D
);
always @(posedge C, posedge R) always @(posedge C, posedge R)
if (R) if (R)
Q <= 0; Q <= 0;
@ -232,7 +288,13 @@ module SB_DFFER (output `SB_DFF_REG, input C, E, R, D);
Q <= D; Q <= D;
endmodule endmodule
module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D); module SB_DFFESS (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, S, D
);
always @(posedge C) always @(posedge C)
if (E) begin if (E) begin
if (S) if (S)
@ -242,7 +304,13 @@ module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D);
end end
endmodule endmodule
module SB_DFFES (output `SB_DFF_REG, input C, E, S, D); module SB_DFFES (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, S, D
);
always @(posedge C, posedge S) always @(posedge C, posedge S)
if (S) if (S)
Q <= 1; Q <= 1;
@ -252,18 +320,36 @@ endmodule
// Negative Edge SiliconBlue FF Cells // Negative Edge SiliconBlue FF Cells
module SB_DFFN (output `SB_DFF_REG, input C, D); module SB_DFFN (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, D
);
always @(negedge C) always @(negedge C)
Q <= D; Q <= D;
endmodule endmodule
module SB_DFFNE (output `SB_DFF_REG, input C, E, D); module SB_DFFNE (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, D
);
always @(negedge C) always @(negedge C)
if (E) if (E)
Q <= D; Q <= D;
endmodule endmodule
module SB_DFFNSR (output `SB_DFF_REG, input C, R, D); module SB_DFFNSR (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, R, D
);
always @(negedge C) always @(negedge C)
if (R) if (R)
Q <= 0; Q <= 0;
@ -271,7 +357,13 @@ module SB_DFFNSR (output `SB_DFF_REG, input C, R, D);
Q <= D; Q <= D;
endmodule endmodule
module SB_DFFNR (output `SB_DFF_REG, input C, R, D); module SB_DFFNR (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, R, D
);
always @(negedge C, posedge R) always @(negedge C, posedge R)
if (R) if (R)
Q <= 0; Q <= 0;
@ -279,7 +371,13 @@ module SB_DFFNR (output `SB_DFF_REG, input C, R, D);
Q <= D; Q <= D;
endmodule endmodule
module SB_DFFNSS (output `SB_DFF_REG, input C, S, D); module SB_DFFNSS (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, S, D
);
always @(negedge C) always @(negedge C)
if (S) if (S)
Q <= 1; Q <= 1;
@ -287,7 +385,13 @@ module SB_DFFNSS (output `SB_DFF_REG, input C, S, D);
Q <= D; Q <= D;
endmodule endmodule
module SB_DFFNS (output `SB_DFF_REG, input C, S, D); module SB_DFFNS (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, S, D
);
always @(negedge C, posedge S) always @(negedge C, posedge S)
if (S) if (S)
Q <= 1; Q <= 1;
@ -295,7 +399,13 @@ module SB_DFFNS (output `SB_DFF_REG, input C, S, D);
Q <= D; Q <= D;
endmodule endmodule
module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D); module SB_DFFNESR (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, R, D
);
always @(negedge C) always @(negedge C)
if (E) begin if (E) begin
if (R) if (R)
@ -305,7 +415,13 @@ module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D);
end end
endmodule endmodule
module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D); module SB_DFFNER (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, R, D
);
always @(negedge C, posedge R) always @(negedge C, posedge R)
if (R) if (R)
Q <= 0; Q <= 0;
@ -313,7 +429,13 @@ module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D);
Q <= D; Q <= D;
endmodule endmodule
module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D); module SB_DFFNESS (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, S, D
);
always @(negedge C) always @(negedge C)
if (E) begin if (E) begin
if (S) if (S)
@ -323,7 +445,13 @@ module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D);
end end
endmodule endmodule
module SB_DFFNES (output `SB_DFF_REG, input C, E, S, D); module SB_DFFNES (
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output `SB_DFF_REG,
input C, E, S, D
);
always @(negedge C, posedge S) always @(negedge C, posedge S)
if (S) if (S)
Q <= 1; Q <= 1;
@ -334,6 +462,9 @@ endmodule
// SiliconBlue RAM Cells // SiliconBlue RAM Cells
module SB_RAM40_4K ( 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
output [15:0] RDATA, output [15:0] RDATA,
input RCLK, RCLKE, RE, input RCLK, RCLKE, RE,
input [10:0] RADDR, input [10:0] RADDR,
@ -502,6 +633,9 @@ module SB_RAM40_4K (
endmodule endmodule
module SB_RAM40_4KNR ( 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
output [15:0] RDATA, output [15:0] RDATA,
input RCLKN, RCLKE, RE, input RCLKN, RCLKE, RE,
input [10:0] RADDR, input [10:0] RADDR,
@ -567,6 +701,9 @@ module SB_RAM40_4KNR (
endmodule endmodule
module SB_RAM40_4KNW ( 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
output [15:0] RDATA, output [15:0] RDATA,
input RCLK, RCLKE, RE, input RCLK, RCLKE, RE,
input [10:0] RADDR, input [10:0] RADDR,
@ -632,6 +769,9 @@ module SB_RAM40_4KNW (
endmodule endmodule
module SB_RAM40_4KNRNW ( 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
output [15:0] RDATA, output [15:0] RDATA,
input RCLKN, RCLKE, RE, input RCLKN, RCLKE, RE,
input [10:0] RADDR, input [10:0] RADDR,
@ -700,7 +840,12 @@ endmodule
module ICESTORM_LC ( module ICESTORM_LC (
input I0, I1, I2, I3, CIN, CLK, CEN, SR, input I0, I1, I2, I3, CIN, CLK, CEN, SR,
output LO, O, COUT output LO,
`ABC_ARRIVAL_HX(540)
`ABC_ARRIVAL_LP(796)
`ABC_ARRIVAL_U(1391)
output O,
output COUT
); );
parameter [15:0] LUT_INIT = 0; parameter [15:0] LUT_INIT = 0;
@ -1300,6 +1445,7 @@ module SB_MAC16 (
input ADDSUBTOP, ADDSUBBOT, input ADDSUBTOP, ADDSUBBOT,
input OHOLDTOP, OHOLDBOT, input OHOLDTOP, OHOLDBOT,
input CI, ACCUMCI, SIGNEXTIN, 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 [31:0] O,
output CO, ACCUMCO, SIGNEXTOUT output CO, ACCUMCO, SIGNEXTOUT
); );

View File

@ -238,7 +238,14 @@ struct SynthIce40Pass : public ScriptPass
{ {
if (check_label("begin")) if (check_label("begin"))
{ {
run("read_verilog -icells -lib +/ice40/cells_sim.v"); std::string define;
if (device_opt == "lp")
define = "-D ICE40_LP";
else if (device_opt == "u")
define = "-D ICE40_U";
else
define = "-D ICE40_HX";
run("read_verilog -icells " + define + " -lib +/ice40/cells_sim.v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str())); run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
run("proc"); run("proc");
} }

View File

@ -39,6 +39,9 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_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.box))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.lut)) $(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/abc_xc7_nowide.lut))

123
techlibs/xilinx/abc_map.v Normal file
View File

@ -0,0 +1,123 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
* 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
// ============================================================================
module RAM32X1D (
output DPO, SPO,
input D,
input WCLK,
input WE,
input A0, A1, A2, A3, A4,
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
);
parameter INIT = 32'h0;
parameter IS_WCLK_INVERTED = 1'b0;
wire \$DPO , \$SPO ;
RAM32X1D #(
.INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
) _TECHMAP_REPLACE_ (
.DPO(\$DPO ), .SPO(\$SPO ),
.D(D), .WCLK(WCLK), .WE(WE),
.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));
endmodule
module RAM64X1D (
output DPO, SPO,
input D,
input WCLK,
input WE,
input A0, A1, A2, A3, A4, A5,
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
);
parameter INIT = 64'h0;
parameter IS_WCLK_INVERTED = 1'b0;
wire \$DPO , \$SPO ;
RAM64X1D #(
.INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
) _TECHMAP_REPLACE_ (
.DPO(\$DPO ), .SPO(\$SPO ),
.D(D), .WCLK(WCLK), .WE(WE),
.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));
endmodule
module RAM128X1D (
output DPO, SPO,
input D,
input WCLK,
input WE,
input [6:0] A, DPRA
);
parameter INIT = 128'h0;
parameter IS_WCLK_INVERTED = 1'b0;
wire \$DPO , \$SPO ;
RAM128X1D #(
.INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
) _TECHMAP_REPLACE_ (
.DPO(\$DPO ), .SPO(\$SPO ),
.D(D), .WCLK(WCLK), .WE(WE),
.A(A),
.DPRA(DPRA)
);
\$__ABC_LUT7 dpo (.A(\$DPO ), .S(A), .Y(DPO));
\$__ABC_LUT7 spo (.A(\$SPO ), .S(A), .Y(SPO));
endmodule
module SRL16E (
output Q,
input A0, A1, A2, A3, CE, CLK, D
);
parameter [15:0] INIT = 16'h0000;
parameter [0:0] IS_CLK_INVERTED = 1'b0;
wire \$Q ;
SRL16E #(
.INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
) _TECHMAP_REPLACE_ (
.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));
endmodule
module SRLC32E (
output Q,
output Q31,
input [4:0] A,
input CE, CLK, D
);
parameter [31:0] INIT = 32'h00000000;
parameter [0:0] IS_CLK_INVERTED = 1'b0;
wire \$Q ;
SRLC32E #(
.INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
) _TECHMAP_REPLACE_ (
.Q(\$Q ), .Q31(Q31),
.A(A), .CE(CE), .CLK(CLK), .D(D)
);
\$__ABC_LUT6 q (.A(\$Q ), .S({1'b1, A}), .Y(Q));
endmodule

View File

@ -0,0 +1,34 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
* 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
// ============================================================================
(* abc_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);
endmodule
(* abc_box_id=2000 *)
module \$__ABC_LUT6 (input A, input [5:0] S, output Y);
endmodule
(* abc_box_id=2001 *)
module \$__ABC_LUT7 (input A, input [6:0] S, output Y);
endmodule

View File

@ -0,0 +1,28 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
* 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
// ============================================================================
module \$__ABC_LUT6 (input A, input [5:0] S, output Y);
assign Y = A;
endmodule
module \$__ABC_LUT7 (input A, input [6:0] S, output Y);
assign Y = A;
endmodule

View File

@ -1,4 +1,5 @@
# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf # Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf
# https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf
# NB: Inputs/Outputs must be ordered alphabetically # NB: Inputs/Outputs must be ordered alphabetically
# (with exceptions for carry in/out) # (with exceptions for carry in/out)
@ -14,6 +15,10 @@ F7MUX 1 1 3 1
MUXF8 2 1 3 1 MUXF8 2 1 3 1
104 94 273 104 94 273
# Box containing MUXF7.[AB] + MUXF8,
# 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
# Inputs: I0 I1 I2 I3 S0 S1 # Inputs: I0 I1 I2 I3 S0 S1
# Outputs: O # Outputs: O
$__MUXF78 3 1 6 1 $__MUXF78 3 1 6 1
@ -37,22 +42,20 @@ CARRY4 4 1 10 8
580 526 507 398 385 508 528 378 380 114 580 526 507 398 385 508 528 378 380 114
# SLICEM/A6LUT # SLICEM/A6LUT
# Inputs: A0 A1 A2 A3 A4 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 WCLK WE # Box to emulate comb/seq behaviour of RAMD{32,64} and SRL{16,32}
# Outputs: DPO SPO # Necessary since RAMD* and SRL* have both combinatorial (i.e.
RAM32X1D 5 0 13 2 # same-cycle read operation) and sequential (write operation
- - - - - - 631 472 407 238 127 - - # is only committed on the next clock edge).
631 472 407 238 127 - - - - - - - - # To model the combinatorial path, such cells have to be split
# 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
0 642 631 472 407 238 127
# SLICEM/A6LUT # SLICEM/A6LUT + F7BMUX
# Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE # Box to emulate comb/seq behaviour of RAMD128
# Inputs: A S0 S1 S2 S3 S4 S5 S6
# Outputs: DPO SPO # Outputs: DPO SPO
RAM64X1D 6 0 15 2 $__ABC_LUT7 2001 0 8 1
- - - - - - - 642 631 472 407 238 127 - - 0 1047 1036 877 812 643 532 478
642 631 472 407 238 127 - - - - - - - - -
# SLICEM/A6LUT + F7[AB]MUX
# Inputs: A0 A1 A2 A3 A4 A5 A6 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 DPRA6 WCLK WE
# Outputs: DPO SPO
RAM128X1D 7 0 17 2
- - - - - - - - 1009 998 839 774 605 494 450 - -
1047 1036 877 812 643 532 478 - - - - - - - - - -

View File

@ -331,7 +331,6 @@ module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y)
endmodule endmodule
`endif `endif
`ifndef _ABC
module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1);
output O; output O;
input I0, I1, I2, I3, S0, S1; input I0, I1, I2, I3, S0, S1;
@ -364,4 +363,3 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1);
else else
MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O));
endmodule endmodule
`endif

View File

@ -184,14 +184,6 @@ module MUXF8(output O, input I0, I1, S);
assign O = S ? I1 : I0; assign O = S ? I1 : I0;
endmodule endmodule
`ifdef _ABC
(* abc_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);
endmodule
`endif
module XORCY(output O, input CI, LI); module XORCY(output O, input CI, LI);
assign O = CI ^ LI; assign O = CI ^ LI;
endmodule endmodule
@ -236,7 +228,15 @@ endmodule
`endif `endif
module FDRE (output reg Q, (* clkbuf_sink *) input C, input CE, D, R); // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L238-L250
module FDRE (
(* abc_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
input C,
input CE, D, R
);
parameter [0:0] INIT = 1'b0; parameter [0:0] INIT = 1'b0;
parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0;
@ -248,7 +248,13 @@ module FDRE (output reg Q, (* clkbuf_sink *) input C, input CE, D, R);
endcase endgenerate endcase endgenerate
endmodule endmodule
module FDSE (output reg Q, (* clkbuf_sink *) input C, input CE, D, S); module FDSE (
(* abc_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
input C,
input CE, D, S
);
parameter [0:0] INIT = 1'b1; parameter [0:0] INIT = 1'b1;
parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0;
@ -260,7 +266,13 @@ module FDSE (output reg Q, (* clkbuf_sink *) input C, input CE, D, S);
endcase endgenerate endcase endgenerate
endmodule endmodule
module FDCE (output reg Q, (* clkbuf_sink *) input C, input CE, D, CLR); module FDCE (
(* abc_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
input C,
input CE, D, CLR
);
parameter [0:0] INIT = 1'b0; parameter [0:0] INIT = 1'b0;
parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0;
@ -274,7 +286,13 @@ module FDCE (output reg Q, (* clkbuf_sink *) input C, input CE, D, CLR);
endcase endgenerate endcase endgenerate
endmodule endmodule
module FDPE (output reg Q, (* clkbuf_sink *) input C, input CE, D, PRE); module FDPE (
(* abc_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
input C,
input CE, D, PRE
);
parameter [0:0] INIT = 1'b1; parameter [0:0] INIT = 1'b1;
parameter [0:0] IS_C_INVERTED = 1'b0; parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0;
@ -288,38 +306,61 @@ module FDPE (output reg Q, (* clkbuf_sink *) input C, input CE, D, PRE);
endcase endgenerate endcase endgenerate
endmodule endmodule
module FDRE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, R); module FDRE_1 (
(* abc_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
input C,
input CE, D, R
);
parameter [0:0] INIT = 1'b0; parameter [0:0] INIT = 1'b0;
initial Q <= INIT; initial Q <= INIT;
always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D; always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;
endmodule endmodule
module FDSE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, S); module FDSE_1 (
(* abc_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
input C,
input CE, D, S
);
parameter [0:0] INIT = 1'b1; parameter [0:0] INIT = 1'b1;
initial Q <= INIT; initial Q <= INIT;
always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D; always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D;
endmodule endmodule
module FDCE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, CLR); module FDCE_1 (
(* abc_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
input C,
input CE, D, CLR
);
parameter [0:0] INIT = 1'b0; parameter [0:0] INIT = 1'b0;
initial Q <= INIT; initial Q <= INIT;
always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
endmodule endmodule
module FDPE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, PRE); module FDPE_1 (
(* abc_arrival=303 *)
output reg Q,
(* clkbuf_sink *)
input C,
input CE, D, PRE
);
parameter [0:0] INIT = 1'b1; parameter [0:0] INIT = 1'b1;
initial Q <= INIT; initial Q <= INIT;
always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
endmodule endmodule
(* abc_box_id = 5 *)
module RAM32X1D ( module RAM32X1D (
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
(* abc_arrival=1153 *)
output DPO, SPO, output DPO, SPO,
(* abc_scc_break *)
input D, input D,
(* clkbuf_sink *) (* clkbuf_sink *)
input WCLK, input WCLK,
(* abc_scc_break *)
input WE, input WE,
input A0, A1, A2, A3, A4, input A0, A1, A2, A3, A4,
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4 input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
@ -335,14 +376,13 @@ module RAM32X1D (
always @(posedge clk) if (WE) mem[a] <= D; always @(posedge clk) if (WE) mem[a] <= D;
endmodule endmodule
(* abc_box_id = 6 *)
module RAM64X1D ( module RAM64X1D (
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
(* abc_arrival=1153 *)
output DPO, SPO, output DPO, SPO,
(* abc_scc_break *)
input D, input D,
(* clkbuf_sink *) (* clkbuf_sink *)
input WCLK, input WCLK,
(* abc_scc_break *)
input WE, input WE,
input A0, A1, A2, A3, A4, A5, input A0, A1, A2, A3, A4, A5,
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
@ -358,14 +398,13 @@ module RAM64X1D (
always @(posedge clk) if (WE) mem[a] <= D; always @(posedge clk) if (WE) mem[a] <= D;
endmodule endmodule
(* abc_box_id = 7 *)
module RAM128X1D ( module RAM128X1D (
output DPO, SPO, // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
(* abc_scc_break *) (* abc_arrival=1153 *)
output DPO, SPO,
input D, input D,
(* clkbuf_sink *) (* clkbuf_sink *)
input WCLK, input WCLK,
(* abc_scc_break *)
input WE, input WE,
input [6:0] A, DPRA input [6:0] A, DPRA
); );
@ -379,6 +418,8 @@ module RAM128X1D (
endmodule endmodule
module SRL16E ( module SRL16E (
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905
(* abc_arrival=1472 *)
output Q, output Q,
input A0, A1, A2, A3, CE, input A0, A1, A2, A3, CE,
(* clkbuf_sink *) (* clkbuf_sink *)
@ -423,7 +464,10 @@ module SRLC16E (
endmodule endmodule
module SRLC32E ( module SRLC32E (
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905
(* abc_arrival=1472 *)
output Q, output Q,
(* abc_arrival=1114 *)
output Q31, output Q31,
input [4:0] A, input [4:0] A,
input CE, input CE,

View File

@ -268,9 +268,9 @@ struct SynthXilinxPass : public ScriptPass
{ {
if (check_label("begin")) { if (check_label("begin")) {
if (vpr) if (vpr)
run("read_verilog -lib -icells -D _ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); run("read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");
else else
run("read_verilog -lib -icells -D _ABC +/xilinx/cells_sim.v"); run("read_verilog -lib +/xilinx/cells_sim.v");
run("read_verilog -lib +/xilinx/cells_xtra.v"); run("read_verilog -lib +/xilinx/cells_xtra.v");
@ -408,7 +408,7 @@ struct SynthXilinxPass : public ScriptPass
} }
if (check_label("map_cells")) { if (check_label("map_cells")) {
std::string techmap_args = "-map +/techmap.v -D _ABC -map +/xilinx/cells_map.v"; std::string techmap_args = "-map +/techmap.v -map +/xilinx/cells_map.v";
if (widemux > 0) if (widemux > 0)
techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux); techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux);
run("techmap " + techmap_args); run("techmap " + techmap_args);
@ -428,10 +428,12 @@ struct SynthXilinxPass : public ScriptPass
if (flatten_before_abc) if (flatten_before_abc)
run("flatten"); run("flatten");
if (help_mode) if (help_mode)
run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut', option for '-retime')"); run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut'; option for '-retime')");
else if (abc9) { else if (abc9) {
if (family != "xc7") if (family != "xc7")
log_warning("'synth_xilinx -abc9' currently supports '-family xc7' only.\n"); 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");
if (nowidelut) if (nowidelut)
run("abc9 -lut +/xilinx/abc_xc7_nowide.lut -box +/xilinx/abc_xc7.box -W " + std::to_string(XC7_WIRE_DELAY)); run("abc9 -lut +/xilinx/abc_xc7_nowide.lut -box +/xilinx/abc_xc7.box -W " + std::to_string(XC7_WIRE_DELAY));
else else
@ -449,14 +451,15 @@ struct SynthXilinxPass : public ScriptPass
// has performed any necessary retiming // has performed any necessary retiming
if (!nosrl || help_mode) if (!nosrl || help_mode)
run("xilinx_srl -fixed -minlen 3", "(skip if '-nosrl')"); run("xilinx_srl -fixed -minlen 3", "(skip if '-nosrl')");
std::string techmap_args = "-map +/xilinx/lut_map.v -map +/xilinx/cells_map.v"; std::string techmap_args = "-map +/xilinx/lut_map.v -map +/xilinx/cells_map.v";
if (help_mode) if (help_mode)
techmap_args += " [-map +/xilinx/ff_map.v]"; techmap_args += " [-map +/xilinx/ff_map.v]";
else if (!abc9) else if (abc9)
techmap_args += " -map +/xilinx/ff_map.v"; techmap_args += " -map +/xilinx/abc_unmap.v";
else
techmap_args += " -map +/xilinx/ff_map.v";
run("techmap " + techmap_args); run("techmap " + techmap_args);
if (!abc9) if (!abc9 || help_mode)
run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT", "(without '-abc9' only)"); "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT", "(without '-abc9' only)");
run("clean"); run("clean");

View File

@ -1,3 +1,5 @@
// Max delays from https://github.com/SymbiFlow/prjxray-db/blob/f8e0364116b2983ac72a3dc8c509ea1cc79e2e3d/artix7/timings/BRAM_L.sdf#L138-L147
module RAMB18E1 ( module RAMB18E1 (
(* clkbuf_sink *) (* clkbuf_sink *)
input CLKARDCLK, input CLKARDCLK,
@ -21,9 +23,13 @@ module RAMB18E1 (
input [1:0] WEA, input [1:0] WEA,
input [3:0] WEBWE, input [3:0] WEBWE,
(* abc_arrival=2454 *)
output [15:0] DOADO, output [15:0] DOADO,
(* abc_arrival=2454 *)
output [15:0] DOBDO, output [15:0] DOBDO,
(* abc_arrival=2454 *)
output [1:0] DOPADOP, output [1:0] DOPADOP,
(* abc_arrival=2454 *)
output [1:0] DOPBDOP output [1:0] DOPBDOP
); );
parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
@ -147,9 +153,13 @@ module RAMB36E1 (
input [3:0] WEA, input [3:0] WEA,
input [7:0] WEBWE, input [7:0] WEBWE,
(* abc_arrival=2454 *)
output [31:0] DOADO, output [31:0] DOADO,
(* abc_arrival=2454 *)
output [31:0] DOBDO, output [31:0] DOBDO,
(* abc_arrival=2454 *)
output [3:0] DOPADOP, output [3:0] DOPADOP,
(* abc_arrival=2454 *)
output [3:0] DOPBDOP output [3:0] DOPBDOP
); );
parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;

View File

@ -5,5 +5,7 @@ always @*
endmodule endmodule
module abc9_test028(input i, output o); module abc9_test028(input i, output o);
unknown u(~i, o); wire w;
unknown u(~i, w);
unknown2 u2(w, o);
endmodule endmodule