mirror of https://github.com/YosysHQ/yosys.git
Merge remote-tracking branch 'origin/xc7mux' into xaig
This commit is contained in:
commit
513c962a71
|
@ -17,7 +17,9 @@ Yosys 0.8 .. Yosys 0.8-dev
|
|||
- Added "rename -src"
|
||||
- Added "equiv_opt" pass
|
||||
- Added "read_aiger" frontend
|
||||
- Added "muxpack" pass
|
||||
- "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx"
|
||||
- "synth_xilinx" to now infer wide multiplexers
|
||||
|
||||
|
||||
Yosys 0.7 .. Yosys 0.8
|
||||
|
|
2
Makefile
2
Makefile
|
@ -122,7 +122,7 @@ OBJS = kernel/version_$(GIT_REV).o
|
|||
# is just a symlink to your actual ABC working directory, as 'make mrproper'
|
||||
# will remove the 'abc' directory and you do not want to accidentally
|
||||
# delete your work on ABC..
|
||||
ABCREV = 3709744
|
||||
ABCREV = 62487de
|
||||
ABCPULL = 1
|
||||
ABCURL ?= https://github.com/berkeley-abc/abc
|
||||
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1
|
||||
|
|
|
@ -49,7 +49,8 @@ struct XAigerWriter
|
|||
dict<SigBit, SigBit> not_map, ff_map, alias_map;
|
||||
dict<SigBit, pair<SigBit, SigBit>> and_map;
|
||||
//pool<SigBit> initstate_bits;
|
||||
vector<std::pair<SigBit,int>> ci_bits, co_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::pair<SigBit,SigBit>> ff_bits;
|
||||
|
||||
vector<pair<int, int>> aig_gates;
|
||||
|
@ -152,10 +153,11 @@ struct XAigerWriter
|
|||
undriven_bits.insert(bit);
|
||||
unused_bits.insert(bit);
|
||||
|
||||
if (wire->port_input)
|
||||
input_bits.insert(bit);
|
||||
else if (keep)
|
||||
if (wire->port_input || keep) {
|
||||
if (bit != wirebit)
|
||||
alias_map[bit] = wirebit;
|
||||
input_bits.insert(wirebit);
|
||||
}
|
||||
|
||||
if (wire->port_output || keep) {
|
||||
if (bit != wirebit)
|
||||
|
@ -166,7 +168,7 @@ struct XAigerWriter
|
|||
}
|
||||
|
||||
for (auto bit : input_bits)
|
||||
undriven_bits.erase(bit);
|
||||
undriven_bits.erase(sigmap(bit));
|
||||
|
||||
for (auto bit : output_bits)
|
||||
if (!bit.wire->port_input)
|
||||
|
@ -179,15 +181,17 @@ struct XAigerWriter
|
|||
for (auto cell : module->cells())
|
||||
{
|
||||
RTLIL::Module* inst_module = module->design->module(cell->type);
|
||||
bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false;
|
||||
bool known_type = yosys_celltypes.cell_known(cell->type);
|
||||
bool builtin_type = yosys_celltypes.cell_known(cell->type);
|
||||
bool abc_type = inst_module && inst_module->attributes.count("\\abc_box_id");
|
||||
|
||||
if (!holes_mode) {
|
||||
toposort.node(cell->name);
|
||||
for (const auto &conn : cell->connections())
|
||||
{
|
||||
for (const auto &conn : cell->connections()) {
|
||||
if (!builtin_type && !abc_type)
|
||||
continue;
|
||||
|
||||
if (!cell->type.in("$_NOT_", "$_AND_")) {
|
||||
if (known_type) {
|
||||
if (builtin_type) {
|
||||
if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA"))
|
||||
continue;
|
||||
if (cell->type == "$memrd" && conn.first == "\\DATA")
|
||||
|
@ -198,7 +202,7 @@ struct XAigerWriter
|
|||
RTLIL::Wire* inst_module_port = inst_module->wire(conn.first);
|
||||
log_assert(inst_module_port);
|
||||
|
||||
if (inst_module_port->attributes.count("\\abc_flop_q"))
|
||||
if (inst_module_port->port_output && inst_module_port->attributes.count("\\abc_flop_q"))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -256,22 +260,28 @@ struct XAigerWriter
|
|||
// continue;
|
||||
//}
|
||||
|
||||
bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false;
|
||||
if (inst_flop) {
|
||||
SigBit d, q;
|
||||
for (const auto &c : cell->connections()) {
|
||||
for (auto b : c.second.bits()) {
|
||||
auto is_input = cell->input(c.first);
|
||||
auto is_output = cell->output(c.first);
|
||||
log_assert(is_input || is_output);
|
||||
if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) {
|
||||
SigBit I = sigmap(b);
|
||||
if (I != b)
|
||||
alias_map[b] = I;
|
||||
RTLIL::Wire* port = inst_module->wire(c.first);
|
||||
for (auto b : c.second.bits()) {
|
||||
if (is_input && port->attributes.count("\\abc_flop_d")) {
|
||||
d = b;
|
||||
SigBit I = sigmap(d);
|
||||
if (I != d)
|
||||
alias_map[I] = d;
|
||||
unused_bits.erase(d);
|
||||
}
|
||||
if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) {
|
||||
SigBit O = sigmap(b);
|
||||
q = O;
|
||||
if (is_output && port->attributes.count("\\abc_flop_q")) {
|
||||
q = b;
|
||||
SigBit O = sigmap(q);
|
||||
if (O != q)
|
||||
alias_map[O] = q;
|
||||
undriven_bits.erase(O);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -279,7 +289,6 @@ struct XAigerWriter
|
|||
abc_box_seen = inst_module->attributes.count("\\abc_box_id");
|
||||
|
||||
ff_bits.emplace_back(d, q);
|
||||
undriven_bits.erase(q);
|
||||
}
|
||||
else if (inst_module && inst_module->attributes.count("\\abc_box_id")) {
|
||||
abc_box_seen = true;
|
||||
|
@ -303,8 +312,10 @@ struct XAigerWriter
|
|||
}
|
||||
}
|
||||
if (is_output) {
|
||||
input_bits.insert(b);
|
||||
SigBit O = sigmap(b);
|
||||
input_bits.insert(O);
|
||||
if (O != b)
|
||||
alias_map[O] = b;
|
||||
undriven_bits.erase(O);
|
||||
}
|
||||
}
|
||||
|
@ -321,19 +332,22 @@ struct XAigerWriter
|
|||
for (auto user_cell : it.second)
|
||||
toposort.edge(driver_cell, user_cell);
|
||||
|
||||
#ifndef NDEBUG
|
||||
pool<RTLIL::Module*> abc_carry_modules;
|
||||
|
||||
#if 0
|
||||
toposort.analyze_loops = true;
|
||||
#endif
|
||||
toposort.sort();
|
||||
#ifndef NDEBUG
|
||||
bool no_loops = toposort.sort();
|
||||
#if 0
|
||||
unsigned i = 0;
|
||||
for (auto &it : toposort.loops) {
|
||||
log(" loop");
|
||||
log(" loop %d", i++);
|
||||
for (auto cell : it)
|
||||
log(" %s", log_id(cell));
|
||||
log("\n");
|
||||
}
|
||||
#endif
|
||||
log_assert(!toposort.found_loops);
|
||||
log_assert(no_loops);
|
||||
|
||||
for (auto cell_name : toposort.sorted) {
|
||||
RTLIL::Cell *cell = module->cell(cell_name);
|
||||
|
@ -341,26 +355,100 @@ struct XAigerWriter
|
|||
if (!box_module || !box_module->attributes.count("\\abc_box_id"))
|
||||
continue;
|
||||
|
||||
// Box ordering is alphabetical
|
||||
cell->connections_.sort(RTLIL::sort_by_id_str());
|
||||
for (const auto &c : cell->connections()) {
|
||||
for (auto b : c.second.bits()) {
|
||||
auto is_input = cell->input(c.first);
|
||||
auto is_output = cell->output(c.first);
|
||||
log_assert(is_input || is_output);
|
||||
if (is_input) {
|
||||
SigBit I = sigmap(b);
|
||||
if (I != b)
|
||||
alias_map[b] = I;
|
||||
co_bits.emplace_back(b, 0);
|
||||
if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) {
|
||||
RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr;
|
||||
RTLIL::Wire* last_in = nullptr, *last_out = nullptr;
|
||||
for (const auto &port_name : box_module->ports) {
|
||||
RTLIL::Wire* w = box_module->wire(port_name);
|
||||
log_assert(w);
|
||||
if (w->port_input) {
|
||||
if (w->attributes.count("\\abc_carry_in")) {
|
||||
log_assert(!carry_in);
|
||||
carry_in = w;
|
||||
}
|
||||
if (is_output) {
|
||||
SigBit O = sigmap(b);
|
||||
ci_bits.emplace_back(O, 0);
|
||||
log_assert(!last_in || last_in->port_id < w->port_id);
|
||||
last_in = w;
|
||||
}
|
||||
if (w->port_output) {
|
||||
if (w->attributes.count("\\abc_carry_out")) {
|
||||
log_assert(!carry_out);
|
||||
carry_out = w;
|
||||
}
|
||||
log_assert(!last_out || last_out->port_id < w->port_id);
|
||||
last_out = w;
|
||||
}
|
||||
}
|
||||
|
||||
if (carry_in) {
|
||||
log_assert(last_in);
|
||||
std::swap(box_module->ports[carry_in->port_id-1], box_module->ports[last_in->port_id-1]);
|
||||
std::swap(carry_in->port_id, last_in->port_id);
|
||||
}
|
||||
if (carry_out) {
|
||||
log_assert(last_out);
|
||||
std::swap(box_module->ports[carry_out->port_id-1], box_module->ports[last_out->port_id-1]);
|
||||
std::swap(carry_out->port_id, last_out->port_id);
|
||||
}
|
||||
}
|
||||
|
||||
// Fully pad all unused input connections of this box cell with S0
|
||||
// Fully pad all undriven output connections of this box cell with anonymous wires
|
||||
// NB: Assume box_module->ports are sorted alphabetically
|
||||
// (as RTLIL::Module::fixup_ports() would do)
|
||||
for (const auto &port_name : box_module->ports) {
|
||||
RTLIL::Wire* w = box_module->wire(port_name);
|
||||
log_assert(w);
|
||||
auto it = cell->connections_.find(port_name);
|
||||
if (w->port_input) {
|
||||
RTLIL::SigSpec rhs;
|
||||
if (it != cell->connections_.end()) {
|
||||
if (GetSize(it->second) < GetSize(w))
|
||||
it->second.append(RTLIL::SigSpec(RTLIL::S0, GetSize(w)-GetSize(it->second)));
|
||||
rhs = it->second;
|
||||
}
|
||||
else {
|
||||
rhs = RTLIL::SigSpec(RTLIL::S0, GetSize(w));
|
||||
cell->setPort(port_name, rhs);
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
for (const auto &b : rhs.bits()) {
|
||||
SigBit I = sigmap(b);
|
||||
if (I != b)
|
||||
alias_map[b] = I;
|
||||
co_bits.emplace_back(b, cell, port_name, offset++, 0);
|
||||
unused_bits.erase(b);
|
||||
}
|
||||
}
|
||||
if (w->port_output) {
|
||||
RTLIL::SigSpec rhs;
|
||||
auto it = cell->connections_.find(w->name);
|
||||
if (it != cell->connections_.end()) {
|
||||
if (GetSize(it->second) < GetSize(w))
|
||||
it->second.append(module->addWire(NEW_ID, GetSize(w)-GetSize(it->second)));
|
||||
rhs = it->second;
|
||||
}
|
||||
else {
|
||||
rhs = module->addWire(NEW_ID, GetSize(w));
|
||||
cell->setPort(port_name, rhs);
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
for (const auto &b : rhs.bits()) {
|
||||
ci_bits.emplace_back(b, cell, port_name, offset++);
|
||||
SigBit O = sigmap(b);
|
||||
if (O != b)
|
||||
alias_map[O] = b;
|
||||
undriven_bits.erase(O);
|
||||
|
||||
auto jt = input_bits.find(b);
|
||||
if (jt != input_bits.end()) {
|
||||
log_assert(b.wire->attributes.count("\\keep"));
|
||||
input_bits.erase(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
box_list.emplace_back(cell);
|
||||
}
|
||||
|
||||
|
@ -375,9 +463,10 @@ struct XAigerWriter
|
|||
if ((wire->port_input && wire->port_output && !undriven_bits.count(bit))
|
||||
|| wire->attributes.count("\\keep")) {
|
||||
log_assert(input_bits.count(bit) && output_bits.count(bit));
|
||||
RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out");
|
||||
RTLIL::IdString wire_name = wire->name.str() + "$inout.out";
|
||||
RTLIL::Wire *new_wire = module->wire(wire_name);
|
||||
if (!new_wire)
|
||||
new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire));
|
||||
new_wire = module->addWire(wire_name, GetSize(wire));
|
||||
SigBit new_bit(new_wire, bit.offset);
|
||||
module->connect(new_bit, bit);
|
||||
if (not_map.count(bit))
|
||||
|
@ -394,13 +483,10 @@ struct XAigerWriter
|
|||
}
|
||||
}
|
||||
|
||||
// Do some CI/CO post-processing:
|
||||
// Erase all POs that are undriven
|
||||
if (!holes_mode)
|
||||
for (auto bit : undriven_bits)
|
||||
output_bits.erase(bit);
|
||||
// CIs cannot be undriven
|
||||
for (const auto &c : ci_bits)
|
||||
undriven_bits.erase(c.first);
|
||||
for (auto bit : unused_bits)
|
||||
undriven_bits.erase(bit);
|
||||
|
||||
|
@ -414,8 +500,20 @@ struct XAigerWriter
|
|||
}
|
||||
|
||||
init_map.sort();
|
||||
if (holes_mode) {
|
||||
struct sort_by_port_id {
|
||||
bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const {
|
||||
return a.wire->port_id < b.wire->port_id;
|
||||
}
|
||||
};
|
||||
input_bits.sort(sort_by_port_id());
|
||||
output_bits.sort(sort_by_port_id());
|
||||
}
|
||||
else {
|
||||
input_bits.sort();
|
||||
output_bits.sort();
|
||||
}
|
||||
|
||||
not_map.sort();
|
||||
ff_map.sort();
|
||||
and_map.sort();
|
||||
|
@ -425,23 +523,24 @@ struct XAigerWriter
|
|||
|
||||
for (auto bit : input_bits) {
|
||||
aig_m++, aig_i++;
|
||||
log_assert(!aig_map.count(bit));
|
||||
aig_map[bit] = 2*aig_m;
|
||||
}
|
||||
|
||||
for (auto &f : ff_bits) {
|
||||
auto bit = f.second;
|
||||
RTLIL::SigBit bit = f.second;
|
||||
aig_m++, aig_i++;
|
||||
log_assert(!aig_map.count(bit));
|
||||
aig_map[bit] = 2*aig_m;
|
||||
}
|
||||
|
||||
dict<SigBit, int> ff_aig_map;
|
||||
for (auto &c : ci_bits) {
|
||||
RTLIL::SigBit bit = std::get<0>(c);
|
||||
aig_m++, aig_i++;
|
||||
c.second = 2*aig_m;
|
||||
auto r = aig_map.insert(std::make_pair(c.first, c.second));
|
||||
if (!r.second) {
|
||||
ff_aig_map[c.first] = c.second;
|
||||
}
|
||||
auto r = aig_map.insert(std::make_pair(bit, 2*aig_m));
|
||||
if (!r.second)
|
||||
ff_aig_map[bit] = 2*aig_m;
|
||||
}
|
||||
|
||||
if (imode && input_bits.empty()) {
|
||||
|
@ -505,9 +604,8 @@ struct XAigerWriter
|
|||
// aig_latchin.push_back(1);
|
||||
|
||||
for (auto &c : co_bits) {
|
||||
RTLIL::SigBit bit = c.first;
|
||||
c.second = aig_o++;
|
||||
ordered_outputs[bit] = c.second;
|
||||
RTLIL::SigBit bit = std::get<0>(c);
|
||||
std::get<4>(c) = ordered_outputs[bit] = aig_o++;
|
||||
aig_outputs.push_back(bit2aig(bit));
|
||||
}
|
||||
|
||||
|
@ -518,7 +616,8 @@ struct XAigerWriter
|
|||
|
||||
for (auto &f : ff_bits) {
|
||||
aig_o++;
|
||||
aig_outputs.push_back(ff_aig_map.at(f.second));
|
||||
RTLIL::SigBit bit = f.second;
|
||||
aig_outputs.push_back(ff_aig_map.at(bit));
|
||||
}
|
||||
|
||||
if (omode && output_bits.empty()) {
|
||||
|
@ -693,49 +792,79 @@ struct XAigerWriter
|
|||
if (omode && num_outputs == 0)
|
||||
num_outputs = 1;
|
||||
write_h_buffer(1);
|
||||
log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size());
|
||||
write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size());
|
||||
log_debug("coNum = %zu\n", num_outputs + ff_bits.size() + co_bits.size());
|
||||
write_h_buffer(num_outputs + ff_bits.size()+ co_bits.size());
|
||||
log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size());
|
||||
write_h_buffer(input_bits.size()+ ff_bits.size());
|
||||
log_debug("poNum = %zu\n", num_outputs + ff_bits.size());
|
||||
write_h_buffer(num_outputs + ff_bits.size());
|
||||
log_debug("boxNum = %zu\n", box_list.size());
|
||||
write_h_buffer(box_list.size());
|
||||
|
||||
RTLIL::Module *holes_module = nullptr;
|
||||
holes_module = module->design->addModule("\\__holes__");
|
||||
log_assert(holes_module);
|
||||
|
||||
int port_id = 1;
|
||||
int box_count = 0;
|
||||
for (auto cell : box_list) {
|
||||
RTLIL::Module* box_module = module->design->module(cell->type);
|
||||
int box_inputs = 0, box_outputs = 0;
|
||||
int box_id = module->design->module(cell->type)->attributes.at("\\abc_box_id").as_int();
|
||||
Cell *holes_cell = nullptr;
|
||||
if (holes_module && !holes_module->cell(stringf("\\u%d", box_id)))
|
||||
holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type);
|
||||
if (box_module->get_bool_attribute("\\whitebox")) {
|
||||
holes_cell = holes_module->addCell(cell->name, cell->type);
|
||||
holes_cell->parameters = cell->parameters;
|
||||
}
|
||||
|
||||
// NB: Assume box_module->ports are sorted alphabetically
|
||||
// (as RTLIL::Module::fixup_ports() would do)
|
||||
for (const auto &port_name : box_module->ports) {
|
||||
RTLIL::Wire *w = box_module->wire(port_name);
|
||||
log_assert(w);
|
||||
RTLIL::Wire *holes_wire;
|
||||
// NB: cell->connections_ already sorted from before
|
||||
for (const auto &c : cell->connections()) {
|
||||
log_assert(c.second.size() == 1);
|
||||
if (cell->input(c.first)) {
|
||||
box_inputs += c.second.size();
|
||||
if (holes_cell) {
|
||||
RTLIL::SigSpec port_wire;
|
||||
if (w->port_input) {
|
||||
for (int i = 0; i < GetSize(w); i++) {
|
||||
box_inputs++;
|
||||
holes_wire = holes_module->wire(stringf("\\i%d", box_inputs));
|
||||
if (!holes_wire) {
|
||||
holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs));
|
||||
holes_wire->port_input = true;
|
||||
holes_wire->port_id = port_id++;
|
||||
holes_module->ports.push_back(holes_wire->name);
|
||||
}
|
||||
holes_cell->setPort(c.first, holes_wire);
|
||||
if (holes_cell)
|
||||
port_wire.append(holes_wire);
|
||||
}
|
||||
if (!port_wire.empty())
|
||||
holes_cell->setPort(w->name, port_wire);
|
||||
}
|
||||
if (cell->output(c.first)) {
|
||||
box_outputs += c.second.size();
|
||||
if (holes_cell) {
|
||||
holes_wire = holes_module->addWire(stringf("\\%s.%s", cell->type.c_str(), c.first.c_str()));
|
||||
if (w->port_output) {
|
||||
box_outputs += GetSize(w);
|
||||
for (int i = 0; i < GetSize(w); i++) {
|
||||
if (GetSize(w) == 1)
|
||||
holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str()));
|
||||
else
|
||||
holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i));
|
||||
holes_wire->port_output = true;
|
||||
holes_cell->setPort(c.first, holes_wire);
|
||||
}
|
||||
holes_wire->port_id = port_id++;
|
||||
holes_module->ports.push_back(holes_wire->name);
|
||||
if (holes_cell)
|
||||
port_wire.append(holes_wire);
|
||||
else
|
||||
holes_module->connect(holes_wire, RTLIL::S0);
|
||||
}
|
||||
if (!port_wire.empty())
|
||||
holes_cell->setPort(w->name, port_wire);
|
||||
}
|
||||
}
|
||||
|
||||
write_h_buffer(box_inputs);
|
||||
write_h_buffer(box_outputs);
|
||||
write_h_buffer(box_id);
|
||||
write_h_buffer(0 /* OldBoxNum */);
|
||||
write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int());
|
||||
write_h_buffer(box_count++);
|
||||
}
|
||||
|
||||
f << "h";
|
||||
|
@ -749,7 +878,7 @@ struct XAigerWriter
|
|||
f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
|
||||
f.write(buffer_str.data(), buffer_str.size());
|
||||
|
||||
if (!ff_bits.empty()) {
|
||||
/*if (!ff_bits.empty())*/ {
|
||||
std::stringstream r_buffer;
|
||||
auto write_r_buffer = [&r_buffer](int i32) {
|
||||
// TODO: Don't assume we're on little endian
|
||||
|
@ -760,6 +889,7 @@ struct XAigerWriter
|
|||
#endif
|
||||
r_buffer.write(reinterpret_cast<const char*>(&i32_be), sizeof(i32_be));
|
||||
};
|
||||
log_debug("flopNum = %zu\n", ff_bits.size());
|
||||
write_r_buffer(ff_bits.size());
|
||||
int mergeability_class = 1;
|
||||
for (auto cell : ff_bits)
|
||||
|
@ -778,13 +908,25 @@ struct XAigerWriter
|
|||
}
|
||||
|
||||
if (holes_module) {
|
||||
holes_module->fixup_ports();
|
||||
// NB: fixup_ports() will sort ports by name
|
||||
//holes_module->fixup_ports();
|
||||
holes_module->check();
|
||||
|
||||
holes_module->design->selection_stack.emplace_back(false);
|
||||
RTLIL::Selection& sel = holes_module->design->selection_stack.back();
|
||||
sel.select(holes_module);
|
||||
|
||||
Pass::call(holes_module->design, "flatten -wb; aigmap; clean -purge");
|
||||
// TODO: Should not need to opt_merge if we only instantiate
|
||||
// each box type once...
|
||||
Pass::call(holes_module->design, "opt_merge -share_all");
|
||||
|
||||
Pass::call(holes_module->design, "flatten -wb");
|
||||
|
||||
// TODO: Should techmap all lib_whitebox-es once
|
||||
//Pass::call(holes_module->design, "techmap");
|
||||
|
||||
Pass::call(holes_module->design, "aigmap");
|
||||
Pass::call(holes_module->design, "clean -purge");
|
||||
|
||||
holes_module->design->selection_stack.pop_back();
|
||||
|
||||
|
@ -835,7 +977,7 @@ struct XAigerWriter
|
|||
|
||||
if (output_bits.count(b)) {
|
||||
int o = ordered_outputs.at(b);
|
||||
output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire));
|
||||
output_lines[o] += stringf("output %lu %d %s\n", o - co_bits.size(), i, log_id(wire));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -865,38 +1007,23 @@ struct XAigerWriter
|
|||
}
|
||||
}
|
||||
|
||||
for (const auto &c : ci_bits) {
|
||||
RTLIL::SigBit b = c.first;
|
||||
RTLIL::Wire *wire = b.wire;
|
||||
int i = b.offset;
|
||||
int a = bit2aig(b);
|
||||
log_assert((a & 1) == 0);
|
||||
input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire));
|
||||
}
|
||||
|
||||
for (const auto &c : co_bits) {
|
||||
RTLIL::SigBit b = c.first;
|
||||
RTLIL::Wire *wire = b.wire;
|
||||
int o = c.second;
|
||||
if (wire)
|
||||
output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(wire));
|
||||
else
|
||||
output_lines[o] += stringf("output %d %d __const%d__\n", o, 0, b.data);
|
||||
}
|
||||
|
||||
input_lines.sort();
|
||||
for (auto &it : input_lines)
|
||||
f << it.second;
|
||||
log_assert(input_lines.size() == input_bits.size() + ci_bits.size());
|
||||
log_assert(input_lines.size() == input_bits.size());
|
||||
|
||||
init_lines.sort();
|
||||
for (auto &it : init_lines)
|
||||
f << it.second;
|
||||
|
||||
int box_count = 0;
|
||||
for (auto cell : box_list)
|
||||
f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name));
|
||||
|
||||
output_lines.sort();
|
||||
for (auto &it : output_lines)
|
||||
f << it.second;
|
||||
log_assert(output_lines.size() == output_bits.size() + co_bits.size());
|
||||
log_assert(output_lines.size() == output_bits.size());
|
||||
if (omode && output_bits.empty())
|
||||
f << "output " << output_lines.size() << " 0 __dummy_o__\n";
|
||||
|
||||
|
|
|
@ -130,10 +130,9 @@ struct JsonWriter
|
|||
f << stringf(" }");
|
||||
first = false;
|
||||
}
|
||||
f << stringf("\n }");
|
||||
f << stringf("\n },\n");
|
||||
|
||||
if (!module->get_blackbox_attribute()) {
|
||||
f << stringf(",\n \"cells\": {");
|
||||
f << stringf(" \"cells\": {");
|
||||
first = true;
|
||||
for (auto c : module->cells()) {
|
||||
if (use_selection && !module->selected(c))
|
||||
|
@ -196,9 +195,7 @@ struct JsonWriter
|
|||
f << stringf(" }");
|
||||
first = false;
|
||||
}
|
||||
f << stringf("\n }");
|
||||
}
|
||||
f << stringf("\n");
|
||||
f << stringf("\n }\n");
|
||||
|
||||
f << stringf(" }");
|
||||
}
|
||||
|
|
|
@ -339,6 +339,9 @@ struct StatPass : public Pass {
|
|||
if (mod->get_bool_attribute("\\top"))
|
||||
top_mod = mod;
|
||||
|
||||
if (mod->attributes.count("\\abc_box_id"))
|
||||
continue;
|
||||
|
||||
statdata_t data(design, mod, width_mode, cell_area, techname);
|
||||
mod_stat[mod->name] = data;
|
||||
|
||||
|
|
|
@ -14,5 +14,6 @@ OBJS += passes/opt/opt_demorgan.o
|
|||
OBJS += passes/opt/rmports.o
|
||||
OBJS += passes/opt/opt_lut.o
|
||||
OBJS += passes/opt/pmux2shiftx.o
|
||||
OBJS += passes/opt/muxpack.o
|
||||
endif
|
||||
|
||||
|
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/sigtools.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct MuxpackWorker
|
||||
{
|
||||
Module *module;
|
||||
SigMap sigmap;
|
||||
|
||||
int mux_count, pmux_count;
|
||||
|
||||
pool<Cell*> remove_cells;
|
||||
|
||||
dict<SigSpec, Cell*> sig_chain_next;
|
||||
dict<SigSpec, Cell*> sig_chain_prev;
|
||||
pool<SigBit> sigbit_with_non_chain_users;
|
||||
pool<Cell*> chain_start_cells;
|
||||
pool<Cell*> candidate_cells;
|
||||
|
||||
void make_sig_chain_next_prev()
|
||||
{
|
||||
for (auto wire : module->wires())
|
||||
{
|
||||
if (wire->port_output || wire->get_bool_attribute("\\keep")) {
|
||||
for (auto bit : sigmap(wire))
|
||||
sigbit_with_non_chain_users.insert(bit);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
if (cell->type.in("$mux", "$pmux") && !cell->get_bool_attribute("\\keep"))
|
||||
{
|
||||
SigSpec a_sig = sigmap(cell->getPort("\\A"));
|
||||
SigSpec b_sig;
|
||||
if (cell->type == "$mux")
|
||||
b_sig = sigmap(cell->getPort("\\B"));
|
||||
SigSpec y_sig = sigmap(cell->getPort("\\Y"));
|
||||
|
||||
if (sig_chain_next.count(a_sig))
|
||||
for (auto a_bit : a_sig.bits())
|
||||
sigbit_with_non_chain_users.insert(a_bit);
|
||||
else {
|
||||
sig_chain_next[a_sig] = cell;
|
||||
candidate_cells.insert(cell);
|
||||
}
|
||||
|
||||
if (!b_sig.empty()) {
|
||||
if (sig_chain_next.count(b_sig))
|
||||
for (auto b_bit : b_sig.bits())
|
||||
sigbit_with_non_chain_users.insert(b_bit);
|
||||
else {
|
||||
sig_chain_next[b_sig] = cell;
|
||||
candidate_cells.insert(cell);
|
||||
}
|
||||
}
|
||||
|
||||
sig_chain_prev[y_sig] = cell;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto conn : cell->connections())
|
||||
if (cell->input(conn.first))
|
||||
for (auto bit : sigmap(conn.second))
|
||||
sigbit_with_non_chain_users.insert(bit);
|
||||
}
|
||||
}
|
||||
|
||||
void find_chain_start_cells()
|
||||
{
|
||||
for (auto cell : candidate_cells)
|
||||
{
|
||||
log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type));
|
||||
|
||||
SigSpec a_sig = cell->getPort("\\A");
|
||||
if (cell->type == "$mux") {
|
||||
SigSpec b_sig = cell->getPort("\\B");
|
||||
if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1)
|
||||
goto start_cell;
|
||||
|
||||
if (!sig_chain_prev.count(a_sig))
|
||||
a_sig = b_sig;
|
||||
}
|
||||
else if (cell->type == "$pmux") {
|
||||
if (!sig_chain_prev.count(a_sig))
|
||||
goto start_cell;
|
||||
}
|
||||
else log_abort();
|
||||
|
||||
{
|
||||
for (auto bit : a_sig.bits())
|
||||
if (sigbit_with_non_chain_users.count(bit))
|
||||
goto start_cell;
|
||||
|
||||
Cell *c1 = sig_chain_prev.at(a_sig);
|
||||
Cell *c2 = cell;
|
||||
|
||||
if (c1->getParam("\\WIDTH") != c2->getParam("\\WIDTH"))
|
||||
goto start_cell;
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
start_cell:
|
||||
chain_start_cells.insert(cell);
|
||||
}
|
||||
}
|
||||
|
||||
vector<Cell*> create_chain(Cell *start_cell)
|
||||
{
|
||||
vector<Cell*> chain;
|
||||
|
||||
Cell *c = start_cell;
|
||||
while (c != nullptr)
|
||||
{
|
||||
chain.push_back(c);
|
||||
|
||||
SigSpec y_sig = sigmap(c->getPort("\\Y"));
|
||||
|
||||
if (sig_chain_next.count(y_sig) == 0)
|
||||
break;
|
||||
|
||||
c = sig_chain_next.at(y_sig);
|
||||
if (chain_start_cells.count(c) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
void process_chain(vector<Cell*> &chain)
|
||||
{
|
||||
if (GetSize(chain) < 2)
|
||||
return;
|
||||
|
||||
int cursor = 0;
|
||||
while (cursor < GetSize(chain))
|
||||
{
|
||||
int cases = GetSize(chain) - cursor;
|
||||
|
||||
Cell *first_cell = chain[cursor];
|
||||
dict<int, SigBit> taps_dict;
|
||||
|
||||
if (cases < 2) {
|
||||
cursor++;
|
||||
continue;
|
||||
}
|
||||
|
||||
Cell *last_cell = chain[cursor+cases-1];
|
||||
|
||||
log("Converting %s.%s ... %s.%s to a pmux with %d cases.\n",
|
||||
log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), cases);
|
||||
|
||||
mux_count += cases;
|
||||
pmux_count += 1;
|
||||
|
||||
first_cell->type = "$pmux";
|
||||
SigSpec b_sig = first_cell->getPort("\\B");
|
||||
SigSpec s_sig = first_cell->getPort("\\S");
|
||||
|
||||
for (int i = 1; i < cases; i++) {
|
||||
Cell* prev_cell = chain[cursor+i-1];
|
||||
Cell* cursor_cell = chain[cursor+i];
|
||||
if (sigmap(prev_cell->getPort("\\Y")) == sigmap(cursor_cell->getPort("\\A"))) {
|
||||
b_sig.append(cursor_cell->getPort("\\B"));
|
||||
s_sig.append(cursor_cell->getPort("\\S"));
|
||||
}
|
||||
else {
|
||||
b_sig.append(cursor_cell->getPort("\\A"));
|
||||
s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort("\\S")));
|
||||
}
|
||||
remove_cells.insert(cursor_cell);
|
||||
}
|
||||
|
||||
first_cell->setPort("\\B", b_sig);
|
||||
first_cell->setPort("\\S", s_sig);
|
||||
first_cell->setParam("\\S_WIDTH", GetSize(s_sig));
|
||||
first_cell->setPort("\\Y", last_cell->getPort("\\Y"));
|
||||
|
||||
cursor += cases;
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
for (auto cell : remove_cells)
|
||||
module->remove(cell);
|
||||
|
||||
remove_cells.clear();
|
||||
sig_chain_next.clear();
|
||||
sig_chain_prev.clear();
|
||||
chain_start_cells.clear();
|
||||
candidate_cells.clear();
|
||||
}
|
||||
|
||||
MuxpackWorker(Module *module) :
|
||||
module(module), sigmap(module), mux_count(0), pmux_count(0)
|
||||
{
|
||||
make_sig_chain_next_prev();
|
||||
find_chain_start_cells();
|
||||
|
||||
for (auto c : chain_start_cells) {
|
||||
vector<Cell*> chain = create_chain(c);
|
||||
process_chain(chain);
|
||||
}
|
||||
|
||||
cleanup();
|
||||
}
|
||||
};
|
||||
|
||||
struct MuxpackPass : public Pass {
|
||||
MuxpackPass() : Pass("muxpack", "$mux/$pmux cascades to $pmux") { }
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" muxpack [selection]\n");
|
||||
log("\n");
|
||||
log("This pass converts cascaded chains of $pmux cells (e.g. those create from case\n");
|
||||
log("constructs) and $mux cells (e.g. those created by if-else constructs) into \n");
|
||||
log("into $pmux cells.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
log_header(design, "Executing MUXPACK pass ($mux cell cascades to $pmux).\n");
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
{
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
int mux_count = 0;
|
||||
int pmux_count = 0;
|
||||
|
||||
for (auto module : design->selected_modules()) {
|
||||
MuxpackWorker worker(module);
|
||||
mux_count += worker.mux_count;
|
||||
pmux_count += worker.pmux_count;
|
||||
}
|
||||
|
||||
log("Converted %d (p)mux cells into %d pmux cells.\n", mux_count, pmux_count);
|
||||
}
|
||||
} MuxpackPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -42,7 +42,7 @@ struct dff_map_bit_info_t {
|
|||
|
||||
bool consider_wire(RTLIL::Wire *wire, std::map<RTLIL::IdString, dff_map_info_t> &dff_dq_map)
|
||||
{
|
||||
if (/*wire->name[0] == '$' ||*/ dff_dq_map.count(wire->name))
|
||||
if (wire->name[0] == '$' || dff_dq_map.count(wire->name))
|
||||
return false;
|
||||
if (wire->port_input)
|
||||
return false;
|
||||
|
|
|
@ -25,8 +25,7 @@
|
|||
#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
|
||||
#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
|
||||
//#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2"
|
||||
//#define ABC_COMMAND_LUT "&st; &sweep; &scorr; &dc2; &retime; &dch -f; &if; &mfs; &ps"
|
||||
#define ABC_COMMAND_LUT "&st; &scorr; &dc2; &retime; &dch -f; &if; &ps -l -m"
|
||||
#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; */"&retime; &dch -f; &ps -l; &if {W} -v; &ps -l"
|
||||
#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P}"
|
||||
#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
|
||||
|
||||
|
@ -273,7 +272,8 @@ failed:
|
|||
void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
|
||||
std::string liberty_file, std::string constr_file, bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
|
||||
bool keepff, std::string delay_target, std::string sop_inputs, std::string sop_products, std::string lutin_shared, bool fast_mode,
|
||||
const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file)
|
||||
const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file,
|
||||
std::string wire_delay)
|
||||
{
|
||||
module = current_module;
|
||||
map_autoidx = autoidx++;
|
||||
|
@ -388,6 +388,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
|||
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 = 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);
|
||||
|
||||
abc_script += stringf("; &write %s/output.aig", tempdir_name.c_str());
|
||||
abc_script = add_echos_to_abc_cmd(abc_script);
|
||||
|
||||
|
@ -424,6 +427,21 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
|||
|
||||
Pass::call(design, stringf("write_xaiger -O -map %s/input.sym %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str()));
|
||||
|
||||
#if 0
|
||||
std::string buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig");
|
||||
std::ifstream ifs;
|
||||
ifs.open(buffer);
|
||||
if (ifs.fail())
|
||||
log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
|
||||
buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
|
||||
log_assert(!design->module("$__abc9__"));
|
||||
AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, false /* wideports */);
|
||||
reader.parse_xaiger();
|
||||
ifs.close();
|
||||
Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "input.v"));
|
||||
design->remove(design->module("$__abc9__"));
|
||||
#endif
|
||||
|
||||
design->selection_stack.pop_back();
|
||||
|
||||
// Now 'unexpose' those wires by undoing
|
||||
|
@ -453,48 +471,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
|||
{
|
||||
log_header(design, "Executing ABC9.\n");
|
||||
|
||||
std::string buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str());
|
||||
f = fopen(buffer.c_str(), "wt");
|
||||
if (f == NULL)
|
||||
log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
|
||||
fprintf(f, "GATE ZERO 1 Y=CONST0;\n");
|
||||
fprintf(f, "GATE ONE 1 Y=CONST1;\n");
|
||||
fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_BUF_"));
|
||||
fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOT_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("AND"))
|
||||
fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_AND_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("NAND"))
|
||||
fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NAND_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("OR"))
|
||||
fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_OR_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("NOR"))
|
||||
fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOR_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("XOR"))
|
||||
fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XOR_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("XNOR"))
|
||||
fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XNOR_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("ANDNOT"))
|
||||
fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ANDNOT_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("ORNOT"))
|
||||
fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ORNOT_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("AOI3"))
|
||||
fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI3_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("OAI3"))
|
||||
fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI3_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("AOI4"))
|
||||
fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI4_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("OAI4"))
|
||||
fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI4_"));
|
||||
if (enabled_gates.empty() || enabled_gates.count("MUX"))
|
||||
fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_MUX_"));
|
||||
if (map_mux4)
|
||||
fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*get_cell_cost("$_MUX_"));
|
||||
if (map_mux8)
|
||||
fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*get_cell_cost("$_MUX_"));
|
||||
if (map_mux16)
|
||||
fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_"));
|
||||
fclose(f);
|
||||
|
||||
std::string buffer;
|
||||
if (!lut_costs.empty()) {
|
||||
buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str());
|
||||
f = fopen(buffer.c_str(), "wt");
|
||||
|
@ -536,19 +513,21 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
|||
log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
|
||||
|
||||
bool builtin_lib = liberty_file.empty();
|
||||
RTLIL::Design *mapped_design = new RTLIL::Design;
|
||||
//parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode);
|
||||
buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
|
||||
AigerReader reader(mapped_design, ifs, "\\netlist", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
|
||||
log_assert(!design->module("$__abc9__"));
|
||||
AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, false /* wideports */);
|
||||
reader.parse_xaiger();
|
||||
|
||||
ifs.close();
|
||||
|
||||
#if 0
|
||||
Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "output.v"));
|
||||
#endif
|
||||
|
||||
log_header(design, "Re-integrating ABC9 results.\n");
|
||||
RTLIL::Module *mapped_mod = mapped_design->modules_["\\netlist"];
|
||||
RTLIL::Module *mapped_mod = design->module("$__abc9__");
|
||||
if (mapped_mod == NULL)
|
||||
log_error("ABC output file does not contain a module `netlist'.\n");
|
||||
Pass::call(mapped_design, "clean");
|
||||
log_error("ABC output file does not contain a module `$__abc9__'.\n");
|
||||
|
||||
pool<RTLIL::SigBit> output_bits;
|
||||
for (auto &it : mapped_mod->wires_) {
|
||||
|
@ -564,7 +543,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
|||
else {
|
||||
// Attempt another wideports_split here because there
|
||||
// exists the possibility that different bits of a port
|
||||
// could be an input and output, therefore parse_xiager()
|
||||
// could be an input and output, therefore parse_xaiger()
|
||||
// could not combine it into a wideport
|
||||
auto r = wideports_split(w->name.str());
|
||||
wire = module->wire(r.first);
|
||||
|
@ -575,6 +554,33 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
|||
}
|
||||
}
|
||||
|
||||
// Remove all AND, NOT, and ABC box instances
|
||||
// in preparation for stitching mapped_mod in
|
||||
dict<IdString, decltype(RTLIL::Cell::parameters)> erased_boxes;
|
||||
for (auto it = module->cells_.begin(); it != module->cells_.end(); ) {
|
||||
RTLIL::Cell* cell = it->second;
|
||||
if (cell->type.in("$_AND_", "$_NOT_")) {
|
||||
it = module->cells_.erase(it);
|
||||
continue;
|
||||
}
|
||||
RTLIL::Module* box_module = design->module(cell->type);
|
||||
if (box_module && box_module->attributes.count("\\abc_box_id")) {
|
||||
erased_boxes.insert(std::make_pair(it->first, std::move(cell->parameters)));
|
||||
it = module->cells_.erase(it);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
// Do the same for module connections
|
||||
for (auto &it : module->connections_) {
|
||||
auto &signal = it.first;
|
||||
auto bits = signal.bits();
|
||||
for (auto &b : bits)
|
||||
if (output_bits.count(b))
|
||||
b = module->addWire(NEW_ID);
|
||||
signal = std::move(bits);
|
||||
}
|
||||
|
||||
std::map<std::string, int> cell_stats;
|
||||
for (auto c : mapped_mod->cells())
|
||||
{
|
||||
|
@ -584,31 +590,39 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
|||
RTLIL::Cell *cell;
|
||||
RTLIL::SigBit a_bit = c->getPort("\\A").as_bit();
|
||||
RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit();
|
||||
if (!lut_costs.empty() || !lut_file.empty()) {
|
||||
// ABC can return NOT gates that drive POs
|
||||
if (a_bit.wire->port_input) {
|
||||
// If it's a NOT gate that comes from a primary input directly
|
||||
// then implement it using a LUT
|
||||
cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())),
|
||||
RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset),
|
||||
RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset),
|
||||
1);
|
||||
if (!a_bit.wire) {
|
||||
c->setPort("\\Y", module->addWire(NEW_ID));
|
||||
module->connect(module->wires_[remap_name(y_bit.wire->name)], RTLIL::S1);
|
||||
}
|
||||
else {
|
||||
// Otherwise, clone the driving LUT to guarantee that we
|
||||
// won't increase the max logic depth
|
||||
else if (!lut_costs.empty() || !lut_file.empty()) {
|
||||
RTLIL::Cell* driving_lut = nullptr;
|
||||
// ABC can return NOT gates that drive POs
|
||||
if (!a_bit.wire->port_input) {
|
||||
// If it's not a NOT gate that that comes from a PI directly,
|
||||
// find the driving LUT and clone that to guarantee that we won't
|
||||
// increase the max logic depth
|
||||
// (TODO: Optimise by not cloning unless will increase depth)
|
||||
RTLIL::IdString driver_name;
|
||||
if (GetSize(a_bit.wire) == 1)
|
||||
driver_name = stringf("%s$lut", a_bit.wire->name.c_str());
|
||||
else
|
||||
driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset);
|
||||
RTLIL::Cell* driver = mapped_mod->cell(driver_name);
|
||||
log_assert(driver);
|
||||
auto driver_a = driver->getPort("\\A").chunks();
|
||||
driving_lut = mapped_mod->cell(driver_name);
|
||||
}
|
||||
|
||||
if (!driving_lut) {
|
||||
// If a driver couldn't be found (could be from PI,
|
||||
// or from a box) then implement using a LUT
|
||||
cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())),
|
||||
RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset),
|
||||
RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset),
|
||||
1);
|
||||
}
|
||||
else {
|
||||
auto driver_a = driving_lut->getPort("\\A").chunks();
|
||||
for (auto &chunk : driver_a)
|
||||
chunk.wire = module->wires_[remap_name(chunk.wire->name)];
|
||||
RTLIL::Const driver_lut = driver->getParam("\\LUT");
|
||||
RTLIL::Const driver_lut = driving_lut->getParam("\\LUT");
|
||||
for (auto &b : driver_lut.bits) {
|
||||
if (b == RTLIL::State::S0) b = RTLIL::State::S1;
|
||||
else if (b == RTLIL::State::S1) b = RTLIL::State::S0;
|
||||
|
@ -618,7 +632,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
|||
RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset),
|
||||
driver_lut);
|
||||
}
|
||||
cell_stats["$lut"]++;
|
||||
}
|
||||
else {
|
||||
cell = module->addCell(remap_name(c->name), "$_NOT_");
|
||||
|
@ -629,165 +642,21 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
|||
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
|
||||
continue;
|
||||
}
|
||||
|
||||
cell_stats[RTLIL::unescape_id(c->type)]++;
|
||||
if (c->type == "\\ZERO" || c->type == "\\ONE") {
|
||||
RTLIL::SigSig conn;
|
||||
conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]);
|
||||
conn.second = RTLIL::SigSpec(c->type == "\\ZERO" ? 0 : 1, 1);
|
||||
module->connect(conn);
|
||||
continue;
|
||||
}
|
||||
if (c->type == "\\BUF") {
|
||||
RTLIL::SigSig conn;
|
||||
conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]);
|
||||
conn.second = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]);
|
||||
module->connect(conn);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c->type == "\\AND" || c->type == "\\OR" || c->type == "\\XOR" || c->type == "\\NAND" || c->type == "\\NOR" ||
|
||||
c->type == "\\XNOR" || c->type == "\\ANDNOT" || c->type == "\\ORNOT") {
|
||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
|
||||
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
|
||||
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
|
||||
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
|
||||
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
|
||||
continue;
|
||||
}
|
||||
if (c->type == "\\MUX") {
|
||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX_");
|
||||
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
|
||||
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
|
||||
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
|
||||
cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
|
||||
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
|
||||
continue;
|
||||
}
|
||||
if (c->type == "\\MUX4") {
|
||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX4_");
|
||||
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
|
||||
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
|
||||
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
|
||||
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
|
||||
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
|
||||
cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
|
||||
cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
|
||||
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
|
||||
continue;
|
||||
}
|
||||
if (c->type == "\\MUX8") {
|
||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX8_");
|
||||
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
|
||||
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
|
||||
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
|
||||
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
|
||||
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
|
||||
cell->setPort("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)]));
|
||||
cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)]));
|
||||
cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)]));
|
||||
cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)]));
|
||||
cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
|
||||
cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
|
||||
cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)]));
|
||||
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
|
||||
continue;
|
||||
}
|
||||
if (c->type == "\\MUX16") {
|
||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX16_");
|
||||
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
|
||||
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
|
||||
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
|
||||
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
|
||||
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
|
||||
cell->setPort("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)]));
|
||||
cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)]));
|
||||
cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)]));
|
||||
cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)]));
|
||||
cell->setPort("\\I", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\I").as_wire()->name)]));
|
||||
cell->setPort("\\J", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\J").as_wire()->name)]));
|
||||
cell->setPort("\\K", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\K").as_wire()->name)]));
|
||||
cell->setPort("\\L", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\L").as_wire()->name)]));
|
||||
cell->setPort("\\M", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\M").as_wire()->name)]));
|
||||
cell->setPort("\\N", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\N").as_wire()->name)]));
|
||||
cell->setPort("\\O", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\O").as_wire()->name)]));
|
||||
cell->setPort("\\P", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\P").as_wire()->name)]));
|
||||
cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
|
||||
cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
|
||||
cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)]));
|
||||
cell->setPort("\\V", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\V").as_wire()->name)]));
|
||||
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
|
||||
continue;
|
||||
}
|
||||
if (c->type == "\\AOI3" || c->type == "\\OAI3") {
|
||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
|
||||
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
|
||||
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
|
||||
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
|
||||
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
|
||||
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
|
||||
continue;
|
||||
}
|
||||
if (c->type == "\\AOI4" || c->type == "\\OAI4") {
|
||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
|
||||
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
|
||||
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
|
||||
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
|
||||
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
|
||||
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
|
||||
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
|
||||
continue;
|
||||
}
|
||||
if (c->type == "\\DFF") {
|
||||
log_assert(clk_sig.size() == 1);
|
||||
RTLIL::Cell *cell;
|
||||
if (en_sig.size() == 0) {
|
||||
cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_");
|
||||
} else {
|
||||
log_assert(en_sig.size() == 1);
|
||||
cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
|
||||
cell->setPort("\\E", en_sig);
|
||||
}
|
||||
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
|
||||
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
|
||||
cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)]));
|
||||
cell->setPort("\\C", clk_sig);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
cell_stats[RTLIL::unescape_id(c->type)]++;
|
||||
|
||||
if (c->type == "\\_const0_" || c->type == "\\_const1_") {
|
||||
RTLIL::SigSig conn;
|
||||
conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->connections().begin()->second.as_wire()->name)]);
|
||||
conn.second = RTLIL::SigSpec(c->type == "\\_const0_" ? 0 : 1, 1);
|
||||
module->connect(conn);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c->type == "\\_dff_") {
|
||||
log_assert(clk_sig.size() == 1);
|
||||
RTLIL::Cell *cell;
|
||||
if (en_sig.size() == 0) {
|
||||
cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_");
|
||||
} else {
|
||||
log_assert(en_sig.size() == 1);
|
||||
cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
|
||||
cell->setPort("\\E", en_sig);
|
||||
}
|
||||
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
|
||||
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
|
||||
cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)]));
|
||||
cell->setPort("\\C", clk_sig);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c->type == "$lut" && GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) {
|
||||
if (c->type == "$lut") {
|
||||
if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) {
|
||||
SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)];
|
||||
SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)];
|
||||
module->connect(my_y, my_a);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto it = erased_boxes.find(c->name);
|
||||
log_assert(it != erased_boxes.end());
|
||||
c->parameters = std::move(it->second);
|
||||
}
|
||||
|
||||
RTLIL::Cell* cell = module->addCell(remap_name(c->name), c->type);
|
||||
|
@ -799,6 +668,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
|||
if (c.width == 0)
|
||||
continue;
|
||||
//log_assert(c.width == 1);
|
||||
if (c.wire)
|
||||
c.wire = module->wires_[remap_name(c.wire->name)];
|
||||
newsig.append(c);
|
||||
}
|
||||
|
@ -836,49 +706,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
|||
for (auto &it : cell_stats)
|
||||
log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second);
|
||||
int in_wires = 0, out_wires = 0;
|
||||
//for (auto &si : signal_list)
|
||||
// if (si.is_port) {
|
||||
// char buffer[100];
|
||||
// snprintf(buffer, 100, "\\n%d", si.id);
|
||||
// RTLIL::SigSig conn;
|
||||
// if (si.type != G(NONE)) {
|
||||
// conn.first = si.bit;
|
||||
// conn.second = RTLIL::SigSpec(module->wires_[remap_name(buffer)]);
|
||||
// out_wires++;
|
||||
// } else {
|
||||
// conn.first = RTLIL::SigSpec(module->wires_[remap_name(buffer)]);
|
||||
// conn.second = si.bit;
|
||||
// in_wires++;
|
||||
// }
|
||||
// module->connect(conn);
|
||||
// }
|
||||
|
||||
// Go through all AND and NOT output connections,
|
||||
// and for those output ports driving wires
|
||||
// also driven by mapped_mod, disconnect them
|
||||
for (auto cell : module->cells()) {
|
||||
if (!cell->type.in("$_AND_", "$_NOT_"))
|
||||
continue;
|
||||
for (auto &it : cell->connections_) {
|
||||
auto port_name = it.first;
|
||||
if (!cell->output(port_name)) continue;
|
||||
auto &signal = it.second;
|
||||
auto bits = signal.bits();
|
||||
for (auto &b : bits)
|
||||
if (output_bits.count(b))
|
||||
b = module->addWire(NEW_ID);
|
||||
signal = std::move(bits);
|
||||
}
|
||||
}
|
||||
// Do the same for module connections
|
||||
for (auto &it : module->connections_) {
|
||||
auto &signal = it.first;
|
||||
auto bits = signal.bits();
|
||||
for (auto &b : bits)
|
||||
if (output_bits.count(b))
|
||||
b = module->addWire(NEW_ID);
|
||||
signal = std::move(bits);
|
||||
}
|
||||
|
||||
// Stitch in mapped_mod's inputs/outputs into module
|
||||
for (auto &it : mapped_mod->wires_) {
|
||||
|
@ -894,7 +721,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
|||
else {
|
||||
// Attempt another wideports_split here because there
|
||||
// exists the possibility that different bits of a port
|
||||
// could be an input and output, therefore parse_xiager()
|
||||
// could be an input and output, therefore parse_xaiger()
|
||||
// could not combine it into a wideport
|
||||
auto r = wideports_split(w->name.str());
|
||||
wire = module->wire(r.first);
|
||||
|
@ -924,7 +751,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
|||
log("ABC RESULTS: input signals: %8d\n", in_wires);
|
||||
log("ABC RESULTS: output signals: %8d\n", out_wires);
|
||||
|
||||
delete mapped_design;
|
||||
design->remove(mapped_mod);
|
||||
}
|
||||
//else
|
||||
//{
|
||||
|
@ -1137,12 +964,17 @@ struct Abc9Pass : public Pass {
|
|||
std::string exe_file = proc_self_dirname() + "yosys-abc";
|
||||
#endif
|
||||
std::string script_file, liberty_file, constr_file, clk_str, box_file, lut_file;
|
||||
std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1";
|
||||
std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1", wire_delay;
|
||||
bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
|
||||
bool show_tempdir = false, sop_mode = false;
|
||||
vector<int> lut_costs;
|
||||
markgroups = false;
|
||||
|
||||
#if 0
|
||||
cleanup = false;
|
||||
show_tempdir = true;
|
||||
#endif
|
||||
|
||||
map_mux4 = false;
|
||||
map_mux8 = false;
|
||||
map_mux16 = false;
|
||||
|
@ -1386,6 +1218,10 @@ struct Abc9Pass : public Pass {
|
|||
box_file = std::string(pwd) + "/" + box_file;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-W" && argidx+1 < args.size()) {
|
||||
wire_delay = "-S " + args[++argidx];
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
@ -1428,7 +1264,7 @@ struct Abc9Pass : public Pass {
|
|||
if (!dff_mode || !clk_str.empty()) {
|
||||
abc9_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
|
||||
delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, mod->selected_cells(), show_tempdir, sop_mode,
|
||||
box_file, lut_file);
|
||||
box_file, lut_file, wire_delay);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1574,7 +1410,7 @@ struct Abc9Pass : public Pass {
|
|||
en_sig = assign_map(std::get<3>(it.first));
|
||||
abc9_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, !clk_sig.empty(), "$",
|
||||
keepff, delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode,
|
||||
box_file, lut_file);
|
||||
box_file, lut_file, wire_delay);
|
||||
assign_map.set(mod);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -293,10 +293,13 @@ struct ShregmapWorker
|
|||
|
||||
if (opts.init || sigbit_init.count(q_bit) == 0)
|
||||
{
|
||||
if (sigbit_chain_next.count(d_bit)) {
|
||||
auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell));
|
||||
if (!r.second) {
|
||||
sigbit_with_non_chain_users.insert(d_bit);
|
||||
} else
|
||||
sigbit_chain_next[d_bit] = cell;
|
||||
Wire *wire = module->addWire(NEW_ID);
|
||||
module->connect(wire, d_bit);
|
||||
sigbit_chain_next.insert(std::make_pair(wire, cell));
|
||||
}
|
||||
|
||||
sigbit_chain_prev[q_bit] = cell;
|
||||
continue;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
# Inputs: C D
|
||||
# Outputs: Q
|
||||
SB_DFF 1 1 2 1
|
||||
SB_DFF 1 0 2 1
|
||||
- -
|
||||
|
||||
# Inputs: C D E
|
||||
|
@ -109,5 +109,5 @@ SB_CARRY 21 1 3 1
|
|||
|
||||
# Inputs: I0 I1 I2 I3
|
||||
# Outputs: O
|
||||
SB_LUT4 22 0 4 1
|
||||
SB_LUT4 22 1 4 1
|
||||
449 400 379 316
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
# Inputs: C D
|
||||
# Outputs: Q
|
||||
SB_DFF 1 1 2 1
|
||||
SB_DFF 1 0 2 1
|
||||
- -
|
||||
|
||||
# Inputs: C D E
|
||||
|
@ -109,5 +109,5 @@ SB_CARRY 21 1 3 1
|
|||
|
||||
# Inputs: I0 I1 I2 I3
|
||||
# Outputs: O
|
||||
SB_LUT4 22 0 4 1
|
||||
SB_LUT4 22 1 4 1
|
||||
465 558 589 661
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
# Inputs: C D
|
||||
# Outputs: Q
|
||||
SB_DFF 1 1 2 1
|
||||
SB_DFF 1 0 2 1
|
||||
- -
|
||||
|
||||
# Inputs: C D E
|
||||
|
@ -109,5 +109,5 @@ SB_CARRY 21 1 3 1
|
|||
|
||||
# Inputs: I0 I1 I2 I3
|
||||
# Outputs: O
|
||||
SB_LUT4 22 0 4 1
|
||||
SB_LUT4 22 1 4 1
|
||||
1285 1231 1205 874
|
||||
|
|
|
@ -53,7 +53,7 @@ module \$lut (A, Y);
|
|||
end else
|
||||
if (WIDTH == 4) begin
|
||||
localparam [15:0] INIT = {LUT[15], LUT[7], LUT[11], LUT[3], LUT[13], LUT[5], LUT[9], LUT[1], LUT[14], LUT[6], LUT[10], LUT[2], LUT[12], LUT[4], LUT[8], LUT[0]};
|
||||
SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
||||
SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
|
||||
.I0(A[3]), .I1(A[2]), .I2(A[1]), .I3(A[0]));
|
||||
end else begin
|
||||
wire _TECHMAP_FAIL_ = 1;
|
||||
|
|
|
@ -127,7 +127,7 @@ endmodule
|
|||
|
||||
// SiliconBlue Logic Cells
|
||||
|
||||
(* abc_box_id = 22 *)
|
||||
(* abc_box_id = 22, lib_whitebox *)
|
||||
module SB_LUT4 (output O, input I0, I1, I2, I3);
|
||||
parameter [15:0] LUT_INIT = 0;
|
||||
wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0];
|
||||
|
@ -136,8 +136,8 @@ module SB_LUT4 (output O, input I0, I1, I2, I3);
|
|||
assign O = I0 ? s1[1] : s1[0];
|
||||
endmodule
|
||||
|
||||
(* abc_box_id = 21, lib_whitebox *)
|
||||
module SB_CARRY (output CO, input I0, I1, CI);
|
||||
(* abc_box_id = 21, abc_carry, lib_whitebox *)
|
||||
module SB_CARRY ((* abc_carry_out *) output CO, input I0, I1, (* abc_carry_in *) input CI);
|
||||
assign CO = (I0 && I1) || ((I0 || I1) && CI);
|
||||
endmodule
|
||||
|
||||
|
@ -145,7 +145,7 @@ endmodule
|
|||
|
||||
(* abc_box_id = 1, abc_flop, lib_whitebox *)
|
||||
module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D);
|
||||
`ifndef ABC_MODEL
|
||||
`ifndef _ABC
|
||||
always @(posedge C)
|
||||
Q <= D;
|
||||
`else
|
||||
|
|
|
@ -240,7 +240,7 @@ struct SynthIce40Pass : public ScriptPass
|
|||
{
|
||||
if (check_label("begin"))
|
||||
{
|
||||
run("read_verilog -lib -D ABC_MODEL +/ice40/cells_sim.v");
|
||||
run("read_verilog -lib -D_ABC +/ice40/cells_sim.v");
|
||||
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
|
||||
run("proc");
|
||||
}
|
||||
|
@ -334,7 +334,7 @@ struct SynthIce40Pass : public ScriptPass
|
|||
if (abc == "abc9")
|
||||
run(abc + stringf(" -dress -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)");
|
||||
else
|
||||
run(abc + " -lut 4", "(skip if -noabc)");
|
||||
run(abc + " -dress -lut 4", "(skip if -noabc)");
|
||||
}
|
||||
run("clean");
|
||||
if (relut || help_mode) {
|
||||
|
|
|
@ -30,6 +30,9 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v))
|
|||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
|
||||
$(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/mux_map.v))
|
||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc.box))
|
||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc.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))
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf
|
||||
|
||||
# F7BMUX slower than F7AMUX
|
||||
# Inputs: I0 I1 S0
|
||||
# Outputs: O
|
||||
F7BMUX 1 1 3 1
|
||||
217 223 296
|
||||
|
||||
# Inputs: I0 I1 S0
|
||||
# Outputs: O
|
||||
MUXF8 2 1 3 1
|
||||
104 94 273
|
||||
|
||||
# CARRY4 + CARRY4_[ABCD]X
|
||||
# Inputs: S0 S1 S2 S3 CYINIT DI0 DI1 DI2 DI3 CI
|
||||
# Outputs: O0 O1 O2 O3 CO0 CO1 CO2 CO3
|
||||
# (NB: carry chain input/output must be last input/output,
|
||||
# swapped with what normally would have been the last
|
||||
# output, here: CI <-> S, CO <-> O
|
||||
CARRY4 3 1 10 8
|
||||
223 - - - 482 - - - - 222
|
||||
400 205 - - 598 407 - - - 334
|
||||
523 558 226 - 584 556 537 - - 239
|
||||
582 618 330 227 642 615 596 438 - 313
|
||||
340 - - - 536 379 - - - 271
|
||||
433 469 - - 494 465 445 - - 157
|
||||
512 548 292 - 592 540 520 356 - 228
|
||||
508 528 378 380 580 526 507 398 385 114
|
||||
|
||||
# SLICEM/A6LUT
|
||||
# Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE
|
||||
# Outputs: DPO SPO
|
||||
RAM64X1D 4 0 15 2
|
||||
- - - - - - - 124 124 124 124 124 124 - -
|
||||
124 124 124 124 124 124 - - - - - - 124 - -
|
||||
|
||||
# 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 5 0 17 2
|
||||
- - - - - - - - 314 314 314 314 314 314 292 - -
|
||||
347 347 347 347 347 347 296 - - - - - - - - - -
|
||||
|
||||
# Inputs: C CE D R
|
||||
# Outputs: Q
|
||||
FDRE 6 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C CE D S
|
||||
# Outputs: Q
|
||||
FDSE 7 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C CE CLR D
|
||||
# Outputs: Q
|
||||
FDCE 8 0 4 1
|
||||
- - 404 -
|
||||
|
||||
# Inputs: C CE D PRE
|
||||
# Outputs: Q
|
||||
FDPE 9 0 4 1
|
||||
- - - 404
|
|
@ -0,0 +1,14 @@
|
|||
# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf
|
||||
|
||||
# K area delay
|
||||
1 1 124
|
||||
2 2 124 235
|
||||
3 3 124 235 399
|
||||
4 3 124 235 399 490
|
||||
5 3 124 235 399 490 620
|
||||
6 5 124 235 399 490 620 632
|
||||
# F7BMUX
|
||||
7 10 296 420 531 695 756 916 928
|
||||
# F8MUX
|
||||
# F8MUX+F7BMUX
|
||||
8 20 273 569 693 804 968 1029 1189 1201
|
|
@ -180,7 +180,7 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
|
|||
|
||||
// First one
|
||||
if (i == 0) begin
|
||||
CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_part
|
||||
CARRY4 carry4_1st_part
|
||||
(
|
||||
.CYINIT(CI),
|
||||
.CI (1'd0),
|
||||
|
@ -207,7 +207,7 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
|
|||
|
||||
// First one
|
||||
if (i == 0) begin
|
||||
CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_full
|
||||
CARRY4 carry4_1st_full
|
||||
(
|
||||
.CYINIT(CI),
|
||||
.CI (1'd0),
|
||||
|
|
|
@ -19,10 +19,10 @@ module RAMB18E1 (
|
|||
input [1:0] WEA,
|
||||
input [3:0] WEBWE,
|
||||
|
||||
output [15:0] DOADO,
|
||||
output [15:0] DOBDO,
|
||||
output [1:0] DOPADOP,
|
||||
output [1:0] DOPBDOP
|
||||
(* abc_flop_q *) output [15:0] DOADO,
|
||||
(* abc_flop_q *) output [15:0] DOBDO,
|
||||
(* abc_flop_q *) output [1:0] DOPADOP,
|
||||
(* abc_flop_q *) output [1:0] DOPBDOP
|
||||
);
|
||||
parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
|
@ -143,10 +143,10 @@ module RAMB36E1 (
|
|||
input [3:0] WEA,
|
||||
input [7:0] WEBWE,
|
||||
|
||||
output [31:0] DOADO,
|
||||
output [31:0] DOBDO,
|
||||
output [3:0] DOPADOP,
|
||||
output [3:0] DOPBDOP
|
||||
(* abc_flop_q *) output [31:0] DOADO,
|
||||
(* abc_flop_q *) output [31:0] DOBDO,
|
||||
(* abc_flop_q *) output [3:0] DOPADOP,
|
||||
(* abc_flop_q *) output [3:0] DOPBDOP
|
||||
);
|
||||
parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* 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
|
||||
|
@ -17,16 +18,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
// Convert negative-polarity reset to positive-polarity
|
||||
(* techmap_celltype = "$_DFF_NN0_" *)
|
||||
module _90_dff_nn0_to_np0 (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
|
||||
(* techmap_celltype = "$_DFF_PN0_" *)
|
||||
module _90_dff_pn0_to_pp0 (input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
|
||||
(* techmap_celltype = "$_DFF_NN1_" *)
|
||||
module _90_dff_nn1_to_np1 (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
|
||||
(* techmap_celltype = "$_DFF_PN1_" *)
|
||||
module _90_dff_pn1_to_pp1 (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
|
||||
|
||||
module \$__SHREG_ (input C, input D, input E, output Q);
|
||||
parameter DEPTH = 0;
|
||||
parameter [DEPTH-1:0] INIT = 0;
|
||||
|
@ -152,5 +143,122 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o
|
|||
endgenerate
|
||||
endmodule
|
||||
|
||||
`ifndef SRL_ONLY
|
||||
`endif
|
||||
module \$__XILINX_SHIFTX (A, B, Y);
|
||||
parameter A_SIGNED = 0;
|
||||
parameter B_SIGNED = 0;
|
||||
parameter A_WIDTH = 1;
|
||||
parameter B_WIDTH = 1;
|
||||
parameter Y_WIDTH = 1;
|
||||
|
||||
input [A_WIDTH-1:0] A;
|
||||
input [B_WIDTH-1:0] B;
|
||||
output [Y_WIDTH-1:0] Y;
|
||||
|
||||
parameter [A_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0;
|
||||
parameter [A_WIDTH-1:0] _TECHMAP_CONSTVAL_A_ = 0;
|
||||
parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0;
|
||||
parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0;
|
||||
|
||||
function integer compute_num_leading_X_in_A;
|
||||
integer i, c;
|
||||
begin
|
||||
compute_num_leading_X_in_A = 0;
|
||||
c = 1;
|
||||
for (i = A_WIDTH-1; i >= 0; i=i-1) begin
|
||||
if (!_TECHMAP_CONSTMSK_A_[i] || _TECHMAP_CONSTVAL_A_[i] !== 1'bx)
|
||||
c = 0;
|
||||
compute_num_leading_X_in_A = compute_num_leading_X_in_A + c;
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
localparam num_leading_X_in_A = compute_num_leading_X_in_A();
|
||||
|
||||
generate
|
||||
genvar i, j;
|
||||
// Bit-blast
|
||||
if (Y_WIDTH > 1) begin
|
||||
for (i = 0; i < Y_WIDTH; i++)
|
||||
\$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i]));
|
||||
end
|
||||
// If the LSB of B is constant zero (and Y_WIDTH is 1) then
|
||||
// we can optimise by removing every other entry from A
|
||||
// and popping the constant zero from B
|
||||
else if (_TECHMAP_CONSTMSK_B_[0] && !_TECHMAP_CONSTVAL_B_[0]) begin
|
||||
wire [(A_WIDTH+1)/2-1:0] A_i;
|
||||
for (i = 0; i < (A_WIDTH+1)/2; i++)
|
||||
assign A_i[i] = A[i*2];
|
||||
\$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y));
|
||||
end
|
||||
// Trim off any leading 1'bx -es in A, and resize B accordingly
|
||||
else if (num_leading_X_in_A > 0) begin
|
||||
localparam A_WIDTH_new = A_WIDTH - num_leading_X_in_A;
|
||||
localparam B_WIDTH_new = $clog2(A_WIDTH_new);
|
||||
\$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH_new), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B[B_WIDTH_new-1:0]), .Y(Y));
|
||||
end
|
||||
else if (B_WIDTH < 3 || A_WIDTH <= 4) begin
|
||||
\$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y));
|
||||
end
|
||||
else if (B_WIDTH == 3) begin
|
||||
localparam a_width0 = 2 ** 2;
|
||||
localparam a_widthN = A_WIDTH - a_width0;
|
||||
wire T0, T1;
|
||||
\$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0));
|
||||
if (a_widthN > 1)
|
||||
\$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1));
|
||||
else
|
||||
assign T1 = A[A_WIDTH-1];
|
||||
MUXF7 fpga_hard_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y));
|
||||
end
|
||||
else if (B_WIDTH == 4) begin
|
||||
localparam a_width0 = 2 ** 2;
|
||||
localparam num_mux8 = A_WIDTH / a_width0;
|
||||
localparam a_widthN = A_WIDTH - num_mux8*a_width0;
|
||||
wire [4-1:0] T;
|
||||
wire T0, T1;
|
||||
for (i = 0; i < 4; i++)
|
||||
if (i < num_mux8)
|
||||
\$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i]));
|
||||
else if (i == num_mux8 && a_widthN > 0) begin
|
||||
if (a_widthN > 1)
|
||||
\$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i]));
|
||||
else
|
||||
assign T[i] = A[A_WIDTH-1];
|
||||
end
|
||||
else
|
||||
assign T[i] = 1'bx;
|
||||
MUXF7 fpga_hard_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[2]), .O(T0));
|
||||
MUXF7 fpga_hard_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[2]), .O(T1));
|
||||
MUXF8 fpga_hard_mux_2 (.I0(T0), .I1(T1), .S(B[3]), .O(Y));
|
||||
end
|
||||
else begin
|
||||
localparam a_width0 = 2 ** 4;
|
||||
localparam num_mux16 = A_WIDTH / a_width0;
|
||||
localparam a_widthN = A_WIDTH - num_mux16*a_width0;
|
||||
wire [(2**(B_WIDTH-4))-1:0] T;
|
||||
for (i = 0; i < 2 ** (B_WIDTH-4); i++)
|
||||
if (i < num_mux16)
|
||||
\$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i]));
|
||||
else if (i == num_mux16 && a_widthN > 0) begin
|
||||
if (a_widthN > 1)
|
||||
\$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i]));
|
||||
else
|
||||
assign T[i] = A[A_WIDTH-1];
|
||||
end
|
||||
else
|
||||
assign T[i] = 1'bx;
|
||||
\$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y));
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
|
||||
module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y);
|
||||
input A, B, C, D, E, F, G, H, S, T, U;
|
||||
output Y;
|
||||
\$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({H,G,F,E,D,C,B,A}), .B({U,T,S}), .Y(Y));
|
||||
endmodule
|
||||
|
||||
module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y);
|
||||
input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V;
|
||||
output Y;
|
||||
\$__XILINX_SHIFTX #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y));
|
||||
endmodule
|
||||
|
|
|
@ -159,10 +159,12 @@ module MUXCY(output O, input CI, DI, S);
|
|||
assign O = S ? CI : DI;
|
||||
endmodule
|
||||
|
||||
(* abc_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 *)
|
||||
module MUXF8(output O, input I0, I1, S);
|
||||
assign O = S ? I1 : I0;
|
||||
endmodule
|
||||
|
@ -171,7 +173,8 @@ module XORCY(output O, input CI, LI);
|
|||
assign O = CI ^ LI;
|
||||
endmodule
|
||||
|
||||
module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S);
|
||||
(* abc_box_id = 3, abc_carry, lib_whitebox *)
|
||||
module CARRY4((* abc_carry_out *) output [3:0] CO, output [3:0] O, (* abc_carry_in *) input CI, input CYINIT, input [3:0] DI, S);
|
||||
assign O = S ^ {CO[2:0], CI | CYINIT};
|
||||
assign CO[0] = S[0] ? CI | CYINIT : DI[0];
|
||||
assign CO[1] = S[1] ? CO[0] : DI[1];
|
||||
|
@ -202,7 +205,7 @@ endmodule
|
|||
|
||||
`endif
|
||||
|
||||
module FDRE (output reg Q, input C, CE, D, R);
|
||||
module FDRE ((* abc_flop_q *) output reg Q, input C, CE, D, R);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_D_INVERTED = 1'b0;
|
||||
|
@ -214,7 +217,7 @@ module FDRE (output reg Q, input C, CE, D, R);
|
|||
endcase endgenerate
|
||||
endmodule
|
||||
|
||||
module FDSE (output reg Q, input C, CE, D, S);
|
||||
module FDSE ((* abc_flop_q *) output reg Q, input C, CE, D, S);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_D_INVERTED = 1'b0;
|
||||
|
@ -226,7 +229,7 @@ module FDSE (output reg Q, input C, CE, D, S);
|
|||
endcase endgenerate
|
||||
endmodule
|
||||
|
||||
module FDCE (output reg Q, input C, CE, D, CLR);
|
||||
module FDCE ((* abc_flop_q *) output reg Q, input C, CE, D, CLR);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_D_INVERTED = 1'b0;
|
||||
|
@ -240,7 +243,7 @@ module FDCE (output reg Q, input C, CE, D, CLR);
|
|||
endcase endgenerate
|
||||
endmodule
|
||||
|
||||
module FDPE (output reg Q, input C, CE, D, PRE);
|
||||
module FDPE ((* abc_flop_q *) output reg Q, input C, CE, D, PRE);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_D_INVERTED = 1'b0;
|
||||
|
@ -254,30 +257,31 @@ module FDPE (output reg Q, input C, CE, D, PRE);
|
|||
endcase endgenerate
|
||||
endmodule
|
||||
|
||||
module FDRE_1 (output reg Q, input C, CE, D, R);
|
||||
module FDRE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, R);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
initial Q <= INIT;
|
||||
always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;
|
||||
endmodule
|
||||
|
||||
module FDSE_1 (output reg Q, input C, CE, D, S);
|
||||
module FDSE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, S);
|
||||
parameter [0:0] INIT = 1'b1;
|
||||
initial Q <= INIT;
|
||||
always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D;
|
||||
endmodule
|
||||
|
||||
module FDCE_1 (output reg Q, input C, CE, D, CLR);
|
||||
module FDCE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, CLR);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
initial Q <= INIT;
|
||||
always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
|
||||
endmodule
|
||||
|
||||
module FDPE_1 (output reg Q, input C, CE, D, PRE);
|
||||
module FDPE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, PRE);
|
||||
parameter [0:0] INIT = 1'b1;
|
||||
initial Q <= INIT;
|
||||
always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
|
||||
endmodule
|
||||
|
||||
//(* abc_box_id = 4 /*, lib_whitebox*/ *)
|
||||
module RAM64X1D (
|
||||
output DPO, SPO,
|
||||
input D, WCLK, WE,
|
||||
|
@ -295,6 +299,7 @@ module RAM64X1D (
|
|||
always @(posedge clk) if (WE) mem[a] <= D;
|
||||
endmodule
|
||||
|
||||
//(* abc_box_id = 5 /*, lib_whitebox*/ *)
|
||||
module RAM128X1D (
|
||||
output DPO, SPO,
|
||||
input D, WCLK, WE,
|
||||
|
@ -310,7 +315,7 @@ module RAM128X1D (
|
|||
endmodule
|
||||
|
||||
module SRL16E (
|
||||
output Q,
|
||||
(* abc_flop_q *) output Q,
|
||||
input A0, A1, A2, A3, CE, CLK, D
|
||||
);
|
||||
parameter [15:0] INIT = 16'h0000;
|
||||
|
@ -328,7 +333,7 @@ module SRL16E (
|
|||
endmodule
|
||||
|
||||
module SRLC32E (
|
||||
output Q,
|
||||
(* abc_flop_q *) output Q,
|
||||
output Q31,
|
||||
input [4:0] A,
|
||||
input CE, CLK, D
|
||||
|
|
|
@ -116,7 +116,7 @@ function xtract_cell_decl()
|
|||
xtract_cell_decl PS7 "(* keep *)"
|
||||
xtract_cell_decl PULLDOWN
|
||||
xtract_cell_decl PULLUP
|
||||
xtract_cell_decl RAM128X1D
|
||||
#xtract_cell_decl RAM128X1D
|
||||
xtract_cell_decl RAM128X1S
|
||||
xtract_cell_decl RAM256X1S
|
||||
xtract_cell_decl RAM32M
|
||||
|
@ -125,7 +125,7 @@ function xtract_cell_decl()
|
|||
xtract_cell_decl RAM32X1S_1
|
||||
xtract_cell_decl RAM32X2S
|
||||
xtract_cell_decl RAM64M
|
||||
xtract_cell_decl RAM64X1D
|
||||
#xtract_cell_decl RAM64X1D
|
||||
xtract_cell_decl RAM64X1S
|
||||
xtract_cell_decl RAM64X1S_1
|
||||
xtract_cell_decl RAM64X2S
|
||||
|
|
|
@ -3655,17 +3655,6 @@ module PULLUP (...);
|
|||
output O;
|
||||
endmodule
|
||||
|
||||
module RAM128X1D (...);
|
||||
parameter [127:0] INIT = 128'h00000000000000000000000000000000;
|
||||
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
||||
output DPO, SPO;
|
||||
input [6:0] A;
|
||||
input [6:0] DPRA;
|
||||
input D;
|
||||
input WCLK;
|
||||
input WE;
|
||||
endmodule
|
||||
|
||||
module RAM128X1S (...);
|
||||
parameter [127:0] INIT = 128'h00000000000000000000000000000000;
|
||||
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
||||
|
@ -3756,13 +3745,6 @@ module RAM64M (...);
|
|||
input WE;
|
||||
endmodule
|
||||
|
||||
module RAM64X1D (...);
|
||||
parameter [63:0] INIT = 64'h0000000000000000;
|
||||
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
||||
output DPO, SPO;
|
||||
input A0, A1, A2, A3, A4, A5, D, DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5, WCLK, WE;
|
||||
endmodule
|
||||
|
||||
module RAM64X1S (...);
|
||||
parameter [63:0] INIT = 64'h0000000000000000;
|
||||
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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 \$shiftx (A, B, Y);
|
||||
parameter A_SIGNED = 0;
|
||||
parameter B_SIGNED = 0;
|
||||
parameter A_WIDTH = 1;
|
||||
parameter B_WIDTH = 1;
|
||||
parameter Y_WIDTH = 1;
|
||||
|
||||
input [A_WIDTH-1:0] A;
|
||||
input [B_WIDTH-1:0] B;
|
||||
output [Y_WIDTH-1:0] Y;
|
||||
|
||||
parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0;
|
||||
parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0;
|
||||
|
||||
generate
|
||||
genvar i, j;
|
||||
// TODO: Check if this opt still necessary
|
||||
if (B_SIGNED) begin
|
||||
if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0)
|
||||
// Optimisation to remove B_SIGNED if sign bit of B is constant-0
|
||||
\$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y));
|
||||
else
|
||||
wire _TECHMAP_FAIL_ = 1;
|
||||
end
|
||||
else if (B_WIDTH < 3 || A_WIDTH <= 4) begin
|
||||
wire _TECHMAP_FAIL_ = 1;
|
||||
end
|
||||
else begin
|
||||
\$__XILINX_SHIFTX #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y));
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
|
@ -0,0 +1,2 @@
|
|||
MUXF8 1 0 3 1
|
||||
1 1 1
|
|
@ -142,3 +142,111 @@ assign b = ~a;
|
|||
(* keep *) reg d;
|
||||
always @* d <= &c;
|
||||
endmodule
|
||||
|
||||
// Citation: https://github.com/alexforencich/verilog-ethernet
|
||||
module abc9_test021(clk, rst, s_eth_hdr_valid, s_eth_hdr_ready, s_eth_dest_mac, s_eth_src_mac, s_eth_type, s_eth_payload_axis_tdata, s_eth_payload_axis_tkeep, s_eth_payload_axis_tvalid, s_eth_payload_axis_tready, s_eth_payload_axis_tlast, s_eth_payload_axis_tid, s_eth_payload_axis_tdest, s_eth_payload_axis_tuser, m_eth_hdr_valid, m_eth_hdr_ready, m_eth_dest_mac, m_eth_src_mac, m_eth_type, m_eth_payload_axis_tdata, m_eth_payload_axis_tkeep, m_eth_payload_axis_tvalid, m_eth_payload_axis_tready, m_eth_payload_axis_tlast, m_eth_payload_axis_tid, m_eth_payload_axis_tdest, m_eth_payload_axis_tuser);
|
||||
input clk;
|
||||
output [47:0] m_eth_dest_mac;
|
||||
input m_eth_hdr_ready;
|
||||
output m_eth_hdr_valid;
|
||||
output [7:0] m_eth_payload_axis_tdata;
|
||||
output [7:0] m_eth_payload_axis_tdest;
|
||||
output [7:0] m_eth_payload_axis_tid;
|
||||
output m_eth_payload_axis_tkeep;
|
||||
output m_eth_payload_axis_tlast;
|
||||
input m_eth_payload_axis_tready;
|
||||
output m_eth_payload_axis_tuser;
|
||||
output m_eth_payload_axis_tvalid;
|
||||
output [47:0] m_eth_src_mac;
|
||||
output [15:0] m_eth_type;
|
||||
input rst;
|
||||
input [191:0] s_eth_dest_mac;
|
||||
output [3:0] s_eth_hdr_ready;
|
||||
input [3:0] s_eth_hdr_valid;
|
||||
input [31:0] s_eth_payload_axis_tdata;
|
||||
input [31:0] s_eth_payload_axis_tdest;
|
||||
input [31:0] s_eth_payload_axis_tid;
|
||||
input [3:0] s_eth_payload_axis_tkeep;
|
||||
input [3:0] s_eth_payload_axis_tlast;
|
||||
output [3:0] s_eth_payload_axis_tready;
|
||||
input [3:0] s_eth_payload_axis_tuser;
|
||||
input [3:0] s_eth_payload_axis_tvalid;
|
||||
input [191:0] s_eth_src_mac;
|
||||
input [63:0] s_eth_type;
|
||||
(* keep *)
|
||||
wire [0:0] grant, request;
|
||||
wire a;
|
||||
not u0 (
|
||||
a,
|
||||
grant[0]
|
||||
);
|
||||
and u1 (
|
||||
request[0],
|
||||
s_eth_hdr_valid[0],
|
||||
a
|
||||
);
|
||||
(* keep *)
|
||||
MUXF8 u2 (
|
||||
.I0(1'bx),
|
||||
.I1(1'bx),
|
||||
.O(o),
|
||||
.S(1'bx)
|
||||
);
|
||||
arbiter arb_inst (
|
||||
.acknowledge(acknowledge),
|
||||
.clk(clk),
|
||||
.grant(grant),
|
||||
.grant_encoded(grant_encoded),
|
||||
.grant_valid(grant_valid),
|
||||
.request(request),
|
||||
.rst(rst)
|
||||
);
|
||||
endmodule
|
||||
|
||||
module arbiter (clk, rst, request, acknowledge, grant, grant_valid, grant_encoded);
|
||||
input [3:0] acknowledge;
|
||||
input clk;
|
||||
output [3:0] grant;
|
||||
output [1:0] grant_encoded;
|
||||
output grant_valid;
|
||||
input [3:0] request;
|
||||
input rst;
|
||||
endmodule
|
||||
|
||||
(* abc_box_id=1 *)
|
||||
module MUXF8(input I0, I1, S, output O);
|
||||
endmodule
|
||||
|
||||
// Citation: https://github.com/alexforencich/verilog-ethernet
|
||||
// TODO: yosys -p "synth_xilinx -abc9 -top abc9_test022" abc9.v -q
|
||||
// returns before b4321a31
|
||||
// Warning: Wire abc9_test022.\m_eth_payload_axis_tkeep [7] is used but has no
|
||||
// driver.
|
||||
// Warning: Wire abc9_test022.\m_eth_payload_axis_tkeep [3] is used but has no
|
||||
// driver.
|
||||
module abc9_test022
|
||||
(
|
||||
input wire clk,
|
||||
input wire i,
|
||||
output wire [7:0] m_eth_payload_axis_tkeep
|
||||
);
|
||||
reg [7:0] m_eth_payload_axis_tkeep_reg = 8'd0;
|
||||
assign m_eth_payload_axis_tkeep = m_eth_payload_axis_tkeep_reg;
|
||||
always @(posedge clk)
|
||||
m_eth_payload_axis_tkeep_reg <= i ? 8'hff : 8'h0f;
|
||||
endmodule
|
||||
|
||||
// Citation: https://github.com/riscv/riscv-bitmanip
|
||||
// TODO: yosys -p "synth_xilinx -abc9 -top abc9_test023" abc9.v -q
|
||||
// returns before 14233843
|
||||
// Warning: Wire abc9_test023.\dout [1] is used but has no driver.
|
||||
module abc9_test023 #(
|
||||
parameter integer N = 2,
|
||||
parameter integer M = 2
|
||||
) (
|
||||
input [7:0] din,
|
||||
output [M-1:0] dout
|
||||
);
|
||||
wire [2*M-1:0] mask = {M{1'b1}};
|
||||
assign dout = (mask << din[N-1:0]) >> M;
|
||||
endmodule
|
||||
|
|
|
@ -19,4 +19,4 @@ fi
|
|||
|
||||
cp ../simple/*.v .
|
||||
DOLLAR='?'
|
||||
exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p 'hierarchy; synth -run coarse; techmap; opt -full; abc9 -lut 4; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'"
|
||||
exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p 'hierarchy; synth -run coarse; opt -full; techmap; abc9 -lut 4 -box ../abc.box; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'"
|
||||
|
|
|
@ -143,6 +143,7 @@ do
|
|||
fn=$(basename $fn)
|
||||
bn=$(basename $bn)
|
||||
|
||||
rm -f ${bn}_ref.fir
|
||||
if [[ "$ext" == "v" ]]; then
|
||||
egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext}
|
||||
elif [[ "$ext" == "aig" ]] || [[ "$ext" == "aag" ]]; then
|
||||
|
@ -150,7 +151,6 @@ do
|
|||
else
|
||||
cp ../${fn} ${bn}_ref.${ext}
|
||||
fi
|
||||
rm -f ${bn}_ref.fir
|
||||
|
||||
if [ ! -f ../${bn}_tb.v ]; then
|
||||
"$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.v
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
module mux_if_unbal_4_1 #(parameter N=4, parameter W=1) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
|
||||
always @*
|
||||
if (s == 0) o <= i[0*W+:W];
|
||||
else if (s == 1) o <= i[1*W+:W];
|
||||
else if (s == 2) o <= i[2*W+:W];
|
||||
else if (s == 3) o <= i[3*W+:W];
|
||||
else o <= {W{1'bx}};
|
||||
endmodule
|
||||
|
||||
module mux_if_unbal_5_3 #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
|
||||
always @* begin
|
||||
o <= {W{1'bx}};
|
||||
if (s == 0) o <= i[0*W+:W];
|
||||
if (s == 1) o <= i[1*W+:W];
|
||||
if (s == 2) o <= i[2*W+:W];
|
||||
if (s == 3) o <= i[3*W+:W];
|
||||
if (s == 4) o <= i[4*W+:W];
|
||||
end
|
||||
endmodule
|
||||
|
||||
module mux_if_unbal_5_3_invert #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
|
||||
always @*
|
||||
if (s != 0)
|
||||
if (s != 1)
|
||||
if (s != 2)
|
||||
if (s != 3)
|
||||
if (s != 4) o <= i[4*W+:W];
|
||||
else o <= i[0*W+:W];
|
||||
else o <= i[3*W+:W];
|
||||
else o <= i[2*W+:W];
|
||||
else o <= i[1*W+:W];
|
||||
else o <= {W{1'bx}};
|
||||
endmodule
|
||||
|
||||
module mux_if_unbal_5_3_width_mismatch #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
|
||||
always @* begin
|
||||
o <= {W{1'bx}};
|
||||
if (s == 0) o <= i[0*W+:W];
|
||||
if (s == 1) o <= i[1*W+:W];
|
||||
if (s == 2) o[W-2:0] <= i[2*W+:W-1];
|
||||
if (s == 3) o <= i[3*W+:W];
|
||||
if (s == 4) o <= i[4*W+:W];
|
||||
end
|
||||
endmodule
|
||||
|
||||
module mux_if_unbal_4_1_missing #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
|
||||
always @* begin
|
||||
if (s == 0) o <= i[0*W+:W];
|
||||
// else if (s == 1) o <= i[1*W+:W];
|
||||
// else if (s == 2) o <= i[2*W+:W];
|
||||
else if (s == 3) o <= i[3*W+:W];
|
||||
else o <= {W{1'bx}};
|
||||
end
|
||||
endmodule
|
||||
|
||||
module mux_if_unbal_5_3_order #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
|
||||
always @* begin
|
||||
o <= {W{1'bx}};
|
||||
if (s == 3) o <= i[3*W+:W];
|
||||
if (s == 2) o <= i[2*W+:W];
|
||||
if (s == 1) o <= i[1*W+:W];
|
||||
if (s == 4) o <= i[4*W+:W];
|
||||
if (s == 0) o <= i[0*W+:W];
|
||||
end
|
||||
endmodule
|
||||
|
||||
module mux_if_unbal_4_1_nonexcl #(parameter N=4, parameter W=1) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
|
||||
always @*
|
||||
if (s == 0) o <= i[0*W+:W];
|
||||
else if (s == 1) o <= i[1*W+:W];
|
||||
else if (s == 2) o <= i[2*W+:W];
|
||||
else if (s == 3) o <= i[3*W+:W];
|
||||
else if (s == 0) o <= {W{1'b0}};
|
||||
else o <= {W{1'bx}};
|
||||
endmodule
|
||||
|
||||
module mux_if_unbal_5_3_nonexcl #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
|
||||
always @* begin
|
||||
o <= {W{1'bx}};
|
||||
if (s == 0) o <= i[0*W+:W];
|
||||
if (s == 1) o <= i[1*W+:W];
|
||||
if (s == 2) o <= i[2*W+:W];
|
||||
if (s == 3) o <= i[3*W+:W];
|
||||
if (s == 4) o <= i[4*W+:W];
|
||||
if (s == 0) o <= i[2*W+:W];
|
||||
end
|
||||
endmodule
|
||||
|
||||
module mux_case_unbal_8_7#(parameter N=8, parameter W=7) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
|
||||
always @* begin
|
||||
o <= {W{1'bx}};
|
||||
case (s)
|
||||
0: o <= i[0*W+:W];
|
||||
default:
|
||||
case (s)
|
||||
1: o <= i[1*W+:W];
|
||||
2: o <= i[2*W+:W];
|
||||
default:
|
||||
case (s)
|
||||
3: o <= i[3*W+:W];
|
||||
4: o <= i[4*W+:W];
|
||||
5: o <= i[5*W+:W];
|
||||
default:
|
||||
case (s)
|
||||
6: o <= i[6*W+:W];
|
||||
default: o <= i[7*W+:W];
|
||||
endcase
|
||||
endcase
|
||||
endcase
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
|
||||
module mux_if_bal_8_2 #(parameter N=8, parameter W=2) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
|
||||
always @*
|
||||
if (s[0] == 1'b0)
|
||||
if (s[1] == 1'b0)
|
||||
if (s[2] == 1'b0)
|
||||
o <= i[0*W+:W];
|
||||
else
|
||||
o <= i[1*W+:W];
|
||||
else
|
||||
if (s[2] == 1'b0)
|
||||
o <= i[2*W+:W];
|
||||
else
|
||||
o <= i[3*W+:W];
|
||||
else
|
||||
if (s[1] == 1'b0)
|
||||
if (s[2] == 1'b0)
|
||||
o <= i[4*W+:W];
|
||||
else
|
||||
o <= i[5*W+:W];
|
||||
else
|
||||
if (s[2] == 1'b0)
|
||||
o <= i[6*W+:W];
|
||||
else
|
||||
o <= i[7*W+:W];
|
||||
endmodule
|
|
@ -0,0 +1,150 @@
|
|||
read_verilog muxpack.v
|
||||
design -save read
|
||||
hierarchy -top mux_if_unbal_4_1
|
||||
prep
|
||||
design -save gold
|
||||
muxpack
|
||||
opt
|
||||
stat
|
||||
select -assert-count 0 t:$mux
|
||||
select -assert-count 1 t:$pmux
|
||||
design -stash gate
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
design -load read
|
||||
hierarchy -top mux_if_unbal_5_3
|
||||
prep
|
||||
design -save gold
|
||||
muxpack
|
||||
opt
|
||||
stat
|
||||
select -assert-count 0 t:$mux
|
||||
select -assert-count 1 t:$pmux
|
||||
design -stash gate
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
design -load read
|
||||
hierarchy -top mux_if_unbal_5_3_invert
|
||||
prep
|
||||
design -save gold
|
||||
muxpack
|
||||
opt
|
||||
stat
|
||||
select -assert-count 0 t:$mux
|
||||
select -assert-count 1 t:$pmux
|
||||
design -stash gate
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
design -load read
|
||||
hierarchy -top mux_if_unbal_5_3_width_mismatch
|
||||
prep
|
||||
design -save gold
|
||||
muxpack
|
||||
opt
|
||||
stat
|
||||
select -assert-count 0 t:$mux
|
||||
select -assert-count 2 t:$pmux
|
||||
design -stash gate
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
design -load read
|
||||
hierarchy -top mux_if_unbal_4_1_missing
|
||||
prep
|
||||
design -save gold
|
||||
muxpack
|
||||
opt
|
||||
stat
|
||||
select -assert-count 0 t:$mux
|
||||
select -assert-count 1 t:$pmux
|
||||
design -stash gate
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
design -load read
|
||||
hierarchy -top mux_if_unbal_5_3_order
|
||||
prep
|
||||
design -save gold
|
||||
muxpack
|
||||
opt
|
||||
stat
|
||||
select -assert-count 0 t:$mux
|
||||
select -assert-count 1 t:$pmux
|
||||
design -stash gate
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
design -load read
|
||||
hierarchy -top mux_if_unbal_4_1_nonexcl
|
||||
prep
|
||||
design -save gold
|
||||
muxpack
|
||||
opt
|
||||
stat
|
||||
select -assert-count 0 t:$mux
|
||||
select -assert-count 1 t:$pmux
|
||||
design -stash gate
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
design -load read
|
||||
hierarchy -top mux_if_unbal_5_3_nonexcl
|
||||
prep
|
||||
design -save gold
|
||||
muxpack
|
||||
opt
|
||||
stat
|
||||
select -assert-count 0 t:$mux
|
||||
select -assert-count 1 t:$pmux
|
||||
design -stash gate
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
design -load read
|
||||
hierarchy -top mux_case_unbal_8_7
|
||||
prep
|
||||
design -save gold
|
||||
muxpack
|
||||
opt
|
||||
stat
|
||||
select -assert-count 0 t:$mux
|
||||
select -assert-count 1 t:$pmux
|
||||
design -stash gate
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
||||
|
||||
design -load read
|
||||
hierarchy -top mux_if_bal_8_2
|
||||
prep
|
||||
design -save gold
|
||||
muxpack
|
||||
opt
|
||||
stat
|
||||
select -assert-count 7 t:$mux
|
||||
select -assert-count 0 t:$pmux
|
||||
design -stash gate
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports miter
|
|
@ -0,0 +1,22 @@
|
|||
module shregmap_test(input i, clk, output [1:0] q);
|
||||
reg head = 1'b0;
|
||||
reg [3:0] shift1 = 4'b0000;
|
||||
reg [3:0] shift2 = 4'b0000;
|
||||
|
||||
always @(posedge clk) begin
|
||||
head <= i;
|
||||
shift1 <= {shift1[2:0], head};
|
||||
shift2 <= {shift2[2:0], head};
|
||||
end
|
||||
|
||||
assign q = {shift2[3], shift1[3]};
|
||||
endmodule
|
||||
|
||||
module $__SHREG_DFF_P_(input C, D, output Q);
|
||||
parameter DEPTH = 1;
|
||||
parameter [DEPTH-1:0] INIT = {DEPTH{1'b0}};
|
||||
reg [DEPTH-1:0] r = INIT;
|
||||
always @(posedge C)
|
||||
r <= { r[DEPTH-2:0], D };
|
||||
assign Q = r[DEPTH-1];
|
||||
endmodule
|
|
@ -0,0 +1,31 @@
|
|||
read_verilog shregmap.v
|
||||
design -copy-to model $__SHREG_DFF_P_
|
||||
hierarchy -top shregmap_test
|
||||
prep
|
||||
design -save gold
|
||||
|
||||
techmap
|
||||
shregmap -init
|
||||
|
||||
opt
|
||||
|
||||
stat
|
||||
# show -width
|
||||
select -assert-count 1 t:$_DFF_P_
|
||||
select -assert-count 2 t:$__SHREG_DFF_P_
|
||||
|
||||
design -stash gate
|
||||
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
design -copy-from model -as $__SHREG_DFF_P_ \$__SHREG_DFF_P_
|
||||
prep
|
||||
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -verify -prove-asserts -show-ports -seq 5 miter
|
||||
|
||||
design -load gold
|
||||
stat
|
||||
|
||||
design -load gate
|
||||
stat
|
Loading…
Reference in New Issue