mirror of https://github.com/YosysHQ/yosys.git
Merge branch 'xaig' into xc7mux
This commit is contained in:
commit
4cfef7897f
|
@ -685,7 +685,7 @@ struct AigerBackend : public Backend {
|
|||
log("invariant constraints.\n");
|
||||
log("\n");
|
||||
log(" -ascii\n");
|
||||
log(" write ASCII version of AGIER format\n");
|
||||
log(" write ASCII version of AIGER format\n");
|
||||
log("\n");
|
||||
log(" -zinit\n");
|
||||
log(" convert FFs to zero-initialized FFs, adding additional inputs for\n");
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/utils.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
@ -46,9 +48,8 @@ struct XAigerWriter
|
|||
pool<SigBit> input_bits, output_bits;
|
||||
dict<SigBit, SigBit> not_map, ff_map, alias_map;
|
||||
dict<SigBit, pair<SigBit, SigBit>> and_map;
|
||||
pool<SigBit> initstate_bits;
|
||||
//pool<SigBit> initstate_bits;
|
||||
vector<std::pair<SigBit,int>> ci_bits, co_bits;
|
||||
dict<IdString, unsigned> type_map;
|
||||
|
||||
vector<pair<int, int>> aig_gates;
|
||||
vector<int> aig_latchin, aig_latchinit, aig_outputs;
|
||||
|
@ -58,11 +59,11 @@ struct XAigerWriter
|
|||
dict<SigBit, int> ordered_outputs;
|
||||
dict<SigBit, int> ordered_latches;
|
||||
|
||||
dict<SigBit, int> init_inputs;
|
||||
int initstate_ff = 0;
|
||||
|
||||
vector<Cell*> box_list;
|
||||
|
||||
//dict<SigBit, int> init_inputs;
|
||||
//int initstate_ff = 0;
|
||||
|
||||
int mkgate(int a0, int a1)
|
||||
{
|
||||
aig_m++, aig_a++;
|
||||
|
@ -76,10 +77,10 @@ struct XAigerWriter
|
|||
{
|
||||
aig_map[bit] = -1;
|
||||
|
||||
if (initstate_bits.count(bit)) {
|
||||
log_assert(initstate_ff > 0);
|
||||
aig_map[bit] = initstate_ff;
|
||||
} else
|
||||
//if (initstate_bits.count(bit)) {
|
||||
// log_assert(initstate_ff > 0);
|
||||
// aig_map[bit] = initstate_ff;
|
||||
//} else
|
||||
if (not_map.count(bit)) {
|
||||
int a = bit2aig(not_map.at(bit)) ^ 1;
|
||||
aig_map[bit] = a;
|
||||
|
@ -102,7 +103,7 @@ struct XAigerWriter
|
|||
return aig_map.at(bit);
|
||||
}
|
||||
|
||||
XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module)
|
||||
XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module)
|
||||
{
|
||||
pool<SigBit> undriven_bits;
|
||||
pool<SigBit> unused_bits;
|
||||
|
@ -159,19 +160,56 @@ struct XAigerWriter
|
|||
}
|
||||
}
|
||||
|
||||
for (auto bit : input_bits) {
|
||||
if (!bit.wire->port_output)
|
||||
undriven_bits.erase(bit);
|
||||
// Erase POs that are also PIs
|
||||
output_bits.erase(bit);
|
||||
}
|
||||
for (auto bit : input_bits)
|
||||
undriven_bits.erase(bit);
|
||||
|
||||
for (auto bit : output_bits)
|
||||
if (!bit.wire->port_input)
|
||||
unused_bits.erase(bit);
|
||||
|
||||
dict<SigBit, pool<IdString>> bit_drivers, bit_users;
|
||||
TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
|
||||
bool abc_box_seen = false;
|
||||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
RTLIL::Module* inst_module = module->design->module(cell->type);
|
||||
bool known_type = yosys_celltypes.cell_known(cell->type);
|
||||
|
||||
if (!holes_mode) {
|
||||
toposort.node(cell->name);
|
||||
for (const auto &conn : cell->connections())
|
||||
{
|
||||
if (!cell->type.in("$_NOT_", "$_AND_")) {
|
||||
if (known_type) {
|
||||
if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA"))
|
||||
continue;
|
||||
if (cell->type == "$memrd" && conn.first == "\\DATA")
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inst_module) {
|
||||
RTLIL::Wire* inst_module_port = inst_module->wire(conn.first);
|
||||
log_assert(inst_module_port);
|
||||
|
||||
if (inst_module_port->attributes.count("\\abc_flop_q"))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (cell->input(conn.first)) {
|
||||
// Ignore inout for the sake of topographical ordering
|
||||
if (cell->output(conn.first)) continue;
|
||||
for (auto bit : sigmap(conn.second))
|
||||
bit_users[bit].insert(cell->name);
|
||||
}
|
||||
|
||||
if (cell->output(conn.first))
|
||||
for (auto bit : sigmap(conn.second))
|
||||
bit_drivers[bit].insert(cell->name);
|
||||
}
|
||||
}
|
||||
|
||||
if (cell->type == "$_NOT_")
|
||||
{
|
||||
SigBit A = sigmap(cell->getPort("\\A").as_bit());
|
||||
|
@ -204,59 +242,100 @@ struct XAigerWriter
|
|||
continue;
|
||||
}
|
||||
|
||||
if (cell->type == "$initstate")
|
||||
{
|
||||
SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
|
||||
undriven_bits.erase(Y);
|
||||
initstate_bits.insert(Y);
|
||||
continue;
|
||||
//if (cell->type == "$initstate")
|
||||
//{
|
||||
// SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
|
||||
// undriven_bits.erase(Y);
|
||||
// initstate_bits.insert(Y);
|
||||
// continue;
|
||||
//}
|
||||
|
||||
if (inst_module && inst_module->attributes.count("\\abc_box_id")) {
|
||||
abc_box_seen = true;
|
||||
}
|
||||
|
||||
RTLIL::Module* box_module = module->design->module(cell->type);
|
||||
bool abc_box = box_module && box_module->attributes.count("\\abc_box_id");
|
||||
|
||||
for (const auto &c : cell->connections()) {
|
||||
/*if (c.second.is_fully_const()) continue;*/
|
||||
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) {
|
||||
/*if (!w->port_input)*/ {
|
||||
SigBit I = sigmap(b);
|
||||
if (I != b)
|
||||
alias_map[b] = I;
|
||||
/*if (!output_bits.count(b))*/
|
||||
if (abc_box)
|
||||
co_bits.emplace_back(b, 0);
|
||||
else if (b.wire) {
|
||||
else {
|
||||
for (const auto &c : cell->connections()) {
|
||||
if (c.second.is_fully_const()) continue;
|
||||
for (auto b : c.second.bits()) {
|
||||
Wire *w = b.wire;
|
||||
if (!w) continue;
|
||||
auto is_input = cell->input(c.first);
|
||||
auto is_output = cell->output(c.first);
|
||||
log_assert(is_input || is_output);
|
||||
if (is_input) {
|
||||
if (!w->port_input) {
|
||||
SigBit I = sigmap(b);
|
||||
if (I != b)
|
||||
alias_map[b] = I;
|
||||
output_bits.insert(b);
|
||||
if (!b.wire->port_input)
|
||||
unused_bits.erase(b);
|
||||
unused_bits.erase(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_output) {
|
||||
SigBit O = sigmap(b);
|
||||
/*if (!input_bits.count(O))*/
|
||||
if (abc_box)
|
||||
ci_bits.emplace_back(O, 0);
|
||||
else {
|
||||
if (is_output) {
|
||||
SigBit O = sigmap(b);
|
||||
input_bits.insert(O);
|
||||
if (!O.wire->port_output)
|
||||
undriven_bits.erase(O);
|
||||
undriven_bits.erase(O);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!type_map.count(cell->type))
|
||||
type_map[cell->type] = type_map.size()+1;
|
||||
}
|
||||
|
||||
if (abc_box)
|
||||
box_list.emplace_back(cell);
|
||||
//log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
|
||||
}
|
||||
|
||||
if (abc_box_seen) {
|
||||
for (auto &it : bit_users)
|
||||
if (bit_drivers.count(it.first))
|
||||
for (auto driver_cell : bit_drivers.at(it.first))
|
||||
for (auto user_cell : it.second)
|
||||
toposort.edge(driver_cell, user_cell);
|
||||
|
||||
#ifndef NDEBUG
|
||||
toposort.analyze_loops = true;
|
||||
#endif
|
||||
toposort.sort();
|
||||
#ifndef NDEBUG
|
||||
for (auto &it : toposort.loops) {
|
||||
log(" loop");
|
||||
for (auto cell : it)
|
||||
log(" %s", log_id(cell));
|
||||
log("\n");
|
||||
}
|
||||
#endif
|
||||
log_assert(!toposort.found_loops);
|
||||
|
||||
for (auto cell_name : toposort.sorted) {
|
||||
RTLIL::Cell *cell = module->cell(cell_name);
|
||||
RTLIL::Module* box_module = module->design->module(cell->type);
|
||||
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 (is_output) {
|
||||
SigBit O = sigmap(b);
|
||||
ci_bits.emplace_back(O, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
box_list.emplace_back(cell);
|
||||
}
|
||||
|
||||
// TODO: Free memory from toposort, bit_drivers, bit_users
|
||||
}
|
||||
|
||||
for (auto bit : input_bits) {
|
||||
RTLIL::Wire *wire = bit.wire;
|
||||
// If encountering an inout port, then create a new wire with $inout.out
|
||||
|
@ -274,27 +353,23 @@ struct XAigerWriter
|
|||
and_map[new_bit] = and_map.at(bit);
|
||||
else if (alias_map.count(bit))
|
||||
alias_map[new_bit] = alias_map.at(bit);
|
||||
else
|
||||
alias_map[new_bit] = bit;
|
||||
output_bits.insert(new_bit);
|
||||
}
|
||||
}
|
||||
|
||||
// Do some CI/CO post-processing:
|
||||
// Erase all POs and COs that are undriven
|
||||
for (auto bit : undriven_bits) {
|
||||
//co_bits.erase(bit);
|
||||
// Erase all POs that are undriven
|
||||
for (auto bit : undriven_bits)
|
||||
output_bits.erase(bit);
|
||||
}
|
||||
// Erase all CIs that are also COs
|
||||
//for (auto bit : co_bits)
|
||||
// ci_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);
|
||||
|
||||
if (!undriven_bits.empty()) {
|
||||
if (!undriven_bits.empty() && !holes_mode) {
|
||||
undriven_bits.sort();
|
||||
for (auto bit : undriven_bits) {
|
||||
log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit));
|
||||
|
@ -313,30 +388,30 @@ struct XAigerWriter
|
|||
aig_map[State::S0] = 0;
|
||||
aig_map[State::S1] = 1;
|
||||
|
||||
for (auto &c : ci_bits) {
|
||||
aig_m++, aig_i++;
|
||||
c.second = 2*aig_m;
|
||||
aig_map[c.first] = c.second;
|
||||
}
|
||||
|
||||
for (auto bit : input_bits) {
|
||||
aig_m++, aig_i++;
|
||||
aig_map[bit] = 2*aig_m;
|
||||
}
|
||||
|
||||
for (auto &c : ci_bits) {
|
||||
aig_m++, aig_i++;
|
||||
c.second = 2*aig_m;
|
||||
aig_map[c.first] = c.second;
|
||||
}
|
||||
|
||||
if (imode && input_bits.empty()) {
|
||||
aig_m++, aig_i++;
|
||||
}
|
||||
|
||||
if (zinit_mode)
|
||||
{
|
||||
for (auto it : ff_map) {
|
||||
if (init_map.count(it.first))
|
||||
continue;
|
||||
aig_m++, aig_i++;
|
||||
init_inputs[it.first] = 2*aig_m;
|
||||
}
|
||||
}
|
||||
//if (zinit_mode)
|
||||
//{
|
||||
// for (auto it : ff_map) {
|
||||
// if (init_map.count(it.first))
|
||||
// continue;
|
||||
// aig_m++, aig_i++;
|
||||
// init_inputs[it.first] = 2*aig_m;
|
||||
// }
|
||||
//}
|
||||
|
||||
for (auto it : ff_map) {
|
||||
aig_m++, aig_l++;
|
||||
|
@ -348,29 +423,29 @@ struct XAigerWriter
|
|||
aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0);
|
||||
}
|
||||
|
||||
if (!initstate_bits.empty() || !init_inputs.empty()) {
|
||||
aig_m++, aig_l++;
|
||||
initstate_ff = 2*aig_m+1;
|
||||
aig_latchinit.push_back(0);
|
||||
}
|
||||
//if (!initstate_bits.empty() || !init_inputs.empty()) {
|
||||
// aig_m++, aig_l++;
|
||||
// initstate_ff = 2*aig_m+1;
|
||||
// aig_latchinit.push_back(0);
|
||||
//}
|
||||
|
||||
if (zinit_mode)
|
||||
{
|
||||
for (auto it : ff_map)
|
||||
{
|
||||
int l = ordered_latches[it.first];
|
||||
//if (zinit_mode)
|
||||
//{
|
||||
// for (auto it : ff_map)
|
||||
// {
|
||||
// int l = ordered_latches[it.first];
|
||||
|
||||
if (aig_latchinit.at(l) == 1)
|
||||
aig_map[it.first] ^= 1;
|
||||
// if (aig_latchinit.at(l) == 1)
|
||||
// aig_map[it.first] ^= 1;
|
||||
|
||||
if (aig_latchinit.at(l) == 2)
|
||||
{
|
||||
int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1);
|
||||
int gated_initin = mkgate(init_inputs[it.first], initstate_ff);
|
||||
aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (aig_latchinit.at(l) == 2)
|
||||
// {
|
||||
// int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1);
|
||||
// int gated_initin = mkgate(init_inputs[it.first], initstate_ff);
|
||||
// aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
for (auto it : ff_map) {
|
||||
int a = bit2aig(it.second);
|
||||
|
@ -381,8 +456,8 @@ struct XAigerWriter
|
|||
aig_latchin.push_back(a);
|
||||
}
|
||||
|
||||
if (!initstate_bits.empty() || !init_inputs.empty())
|
||||
aig_latchin.push_back(1);
|
||||
//if (!initstate_bits.empty() || !init_inputs.empty())
|
||||
// aig_latchin.push_back(1);
|
||||
|
||||
for (auto &c : co_bits) {
|
||||
RTLIL::SigBit bit = c.first;
|
||||
|
@ -517,14 +592,14 @@ struct XAigerWriter
|
|||
symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire)));
|
||||
}
|
||||
|
||||
if (init_inputs.count(sig[i])) {
|
||||
int a = init_inputs.at(sig[i]);
|
||||
log_assert((a & 1) == 0);
|
||||
if (GetSize(wire) != 1)
|
||||
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i));
|
||||
else
|
||||
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire)));
|
||||
}
|
||||
//if (init_inputs.count(sig[i])) {
|
||||
// int a = init_inputs.at(sig[i]);
|
||||
// log_assert((a & 1) == 0);
|
||||
// if (GetSize(wire) != 1)
|
||||
// symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i));
|
||||
// else
|
||||
// symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire)));
|
||||
//}
|
||||
|
||||
if (ordered_latches.count(sig[i])) {
|
||||
int l = ordered_latches.at(sig[i]);
|
||||
|
@ -584,17 +659,17 @@ struct XAigerWriter
|
|||
if (holes_module && !holes_module->cell(stringf("\\u%d", box_id)))
|
||||
holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type);
|
||||
RTLIL::Wire *holes_wire;
|
||||
int num_inputs = 0;
|
||||
// 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) {
|
||||
holes_wire = holes_module->wire(stringf("\\i%d", num_inputs));
|
||||
holes_wire = holes_module->wire(stringf("\\i%d", box_inputs));
|
||||
if (!holes_wire) {
|
||||
holes_wire = holes_module->addWire(stringf("\\i%d", num_inputs));
|
||||
holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs));
|
||||
holes_wire->port_input = true;
|
||||
}
|
||||
++num_inputs;
|
||||
holes_cell->setPort(c.first, holes_wire);
|
||||
}
|
||||
}
|
||||
|
@ -631,12 +706,12 @@ struct XAigerWriter
|
|||
RTLIL::Selection& sel = holes_module->design->selection_stack.back();
|
||||
sel.select(holes_module);
|
||||
|
||||
Pass::call(holes_module->design, "flatten; aigmap");
|
||||
Pass::call(holes_module->design, "flatten -wb; aigmap; clean -purge");
|
||||
|
||||
holes_module->design->selection_stack.pop_back();
|
||||
|
||||
std::stringstream a_buffer;
|
||||
XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/);
|
||||
XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* holes_mode */);
|
||||
writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/);
|
||||
|
||||
f << "a";
|
||||
|
@ -686,12 +761,12 @@ struct XAigerWriter
|
|||
continue;
|
||||
}
|
||||
|
||||
if (init_inputs.count(sig[i])) {
|
||||
int a = init_inputs.at(sig[i]);
|
||||
log_assert((a & 1) == 0);
|
||||
init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire));
|
||||
continue;
|
||||
}
|
||||
//if (init_inputs.count(sig[i])) {
|
||||
// int a = init_inputs.at(sig[i]);
|
||||
// log_assert((a & 1) == 0);
|
||||
// init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire));
|
||||
// continue;
|
||||
//}
|
||||
|
||||
if (ordered_latches.count(sig[i])) {
|
||||
int l = ordered_latches.at(sig[i]);
|
||||
|
@ -716,7 +791,7 @@ struct XAigerWriter
|
|||
RTLIL::SigBit b = c.first;
|
||||
RTLIL::Wire *wire = b.wire;
|
||||
int i = b.offset;
|
||||
int a = c.second;
|
||||
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));
|
||||
}
|
||||
|
@ -769,7 +844,7 @@ struct XAigerBackend : public Backend {
|
|||
log("all unsupported cells will be converted into psuedo-inputs and pseudo-outputs.\n");
|
||||
log("\n");
|
||||
log(" -ascii\n");
|
||||
log(" write ASCII version of AGIER format\n");
|
||||
log(" write ASCII version of AIGER format\n");
|
||||
log("\n");
|
||||
log(" -zinit\n");
|
||||
log(" convert FFs to zero-initialized FFs, adding additional inputs for\n");
|
||||
|
|
|
@ -130,72 +130,75 @@ struct JsonWriter
|
|||
f << stringf(" }");
|
||||
first = false;
|
||||
}
|
||||
f << stringf("\n },\n");
|
||||
f << stringf("\n }");
|
||||
|
||||
f << stringf(" \"cells\": {");
|
||||
first = true;
|
||||
for (auto c : module->cells()) {
|
||||
if (use_selection && !module->selected(c))
|
||||
continue;
|
||||
f << stringf("%s\n", first ? "" : ",");
|
||||
f << stringf(" %s: {\n", get_name(c->name).c_str());
|
||||
f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0");
|
||||
f << stringf(" \"type\": %s,\n", get_name(c->type).c_str());
|
||||
if (aig_mode) {
|
||||
Aig aig(c);
|
||||
if (!aig.name.empty()) {
|
||||
f << stringf(" \"model\": \"%s\",\n", aig.name.c_str());
|
||||
aig_models.insert(aig);
|
||||
if (!module->get_blackbox_attribute()) {
|
||||
f << stringf(",\n \"cells\": {");
|
||||
first = true;
|
||||
for (auto c : module->cells()) {
|
||||
if (use_selection && !module->selected(c))
|
||||
continue;
|
||||
f << stringf("%s\n", first ? "" : ",");
|
||||
f << stringf(" %s: {\n", get_name(c->name).c_str());
|
||||
f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0");
|
||||
f << stringf(" \"type\": %s,\n", get_name(c->type).c_str());
|
||||
if (aig_mode) {
|
||||
Aig aig(c);
|
||||
if (!aig.name.empty()) {
|
||||
f << stringf(" \"model\": \"%s\",\n", aig.name.c_str());
|
||||
aig_models.insert(aig);
|
||||
}
|
||||
}
|
||||
}
|
||||
f << stringf(" \"parameters\": {");
|
||||
write_parameters(c->parameters);
|
||||
f << stringf("\n },\n");
|
||||
f << stringf(" \"attributes\": {");
|
||||
write_parameters(c->attributes);
|
||||
f << stringf("\n },\n");
|
||||
if (c->known()) {
|
||||
f << stringf(" \"port_directions\": {");
|
||||
f << stringf(" \"parameters\": {");
|
||||
write_parameters(c->parameters);
|
||||
f << stringf("\n },\n");
|
||||
f << stringf(" \"attributes\": {");
|
||||
write_parameters(c->attributes);
|
||||
f << stringf("\n },\n");
|
||||
if (c->known()) {
|
||||
f << stringf(" \"port_directions\": {");
|
||||
bool first2 = true;
|
||||
for (auto &conn : c->connections()) {
|
||||
string direction = "output";
|
||||
if (c->input(conn.first))
|
||||
direction = c->output(conn.first) ? "inout" : "input";
|
||||
f << stringf("%s\n", first2 ? "" : ",");
|
||||
f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str());
|
||||
first2 = false;
|
||||
}
|
||||
f << stringf("\n },\n");
|
||||
}
|
||||
f << stringf(" \"connections\": {");
|
||||
bool first2 = true;
|
||||
for (auto &conn : c->connections()) {
|
||||
string direction = "output";
|
||||
if (c->input(conn.first))
|
||||
direction = c->output(conn.first) ? "inout" : "input";
|
||||
f << stringf("%s\n", first2 ? "" : ",");
|
||||
f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str());
|
||||
f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str());
|
||||
first2 = false;
|
||||
}
|
||||
f << stringf("\n },\n");
|
||||
f << stringf("\n }\n");
|
||||
f << stringf(" }");
|
||||
first = false;
|
||||
}
|
||||
f << stringf(" \"connections\": {");
|
||||
bool first2 = true;
|
||||
for (auto &conn : c->connections()) {
|
||||
f << stringf("%s\n", first2 ? "" : ",");
|
||||
f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str());
|
||||
first2 = false;
|
||||
}
|
||||
f << stringf("\n }\n");
|
||||
f << stringf(" }");
|
||||
first = false;
|
||||
}
|
||||
f << stringf("\n },\n");
|
||||
f << stringf("\n },\n");
|
||||
|
||||
f << stringf(" \"netnames\": {");
|
||||
first = true;
|
||||
for (auto w : module->wires()) {
|
||||
if (use_selection && !module->selected(w))
|
||||
continue;
|
||||
f << stringf("%s\n", first ? "" : ",");
|
||||
f << stringf(" %s: {\n", get_name(w->name).c_str());
|
||||
f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0");
|
||||
f << stringf(" \"bits\": %s,\n", get_bits(w).c_str());
|
||||
f << stringf(" \"attributes\": {");
|
||||
write_parameters(w->attributes);
|
||||
f << stringf("\n }\n");
|
||||
f << stringf(" }");
|
||||
first = false;
|
||||
f << stringf(" \"netnames\": {");
|
||||
first = true;
|
||||
for (auto w : module->wires()) {
|
||||
if (use_selection && !module->selected(w))
|
||||
continue;
|
||||
f << stringf("%s\n", first ? "" : ",");
|
||||
f << stringf(" %s: {\n", get_name(w->name).c_str());
|
||||
f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0");
|
||||
f << stringf(" \"bits\": %s,\n", get_bits(w).c_str());
|
||||
f << stringf(" \"attributes\": {");
|
||||
write_parameters(w->attributes);
|
||||
f << stringf("\n }\n");
|
||||
f << stringf(" }");
|
||||
first = false;
|
||||
}
|
||||
f << stringf("\n }");
|
||||
}
|
||||
f << stringf("\n }\n");
|
||||
f << stringf("\n");
|
||||
|
||||
f << stringf(" }");
|
||||
}
|
||||
|
|
|
@ -187,6 +187,10 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
|
|||
{
|
||||
if (width < 0)
|
||||
width = data.bits.size() - offset;
|
||||
if (width == 0) {
|
||||
f << "\"\"";
|
||||
return;
|
||||
}
|
||||
if (nostr)
|
||||
goto dump_hex;
|
||||
if ((data.flags & RTLIL::CONST_FLAG_STRING) == 0 || width != (int)data.bits.size()) {
|
||||
|
@ -340,6 +344,10 @@ void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool no_decima
|
|||
|
||||
void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig)
|
||||
{
|
||||
if (GetSize(sig) == 0) {
|
||||
f << "\"\"";
|
||||
return;
|
||||
}
|
||||
if (sig.is_chunk()) {
|
||||
dump_sigchunk(f, sig.as_chunk());
|
||||
} else {
|
||||
|
|
|
@ -35,9 +35,6 @@
|
|||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
//#define log_debug log
|
||||
#define log_debug(...) ;
|
||||
|
||||
AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports)
|
||||
: design(design), f(f), clk_name(clk_name), map_filename(map_filename), wideports(wideports)
|
||||
{
|
||||
|
@ -368,6 +365,13 @@ void AigerReader::parse_xaiger()
|
|||
f >> s;
|
||||
log_debug("n: '%s'\n", s.c_str());
|
||||
}
|
||||
else if (c == 'a' || c == 'i' || c == 'o' || c == 'h') {
|
||||
uint32_t dataSize = parse_xaiger_literal(f);
|
||||
f.ignore(dataSize);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (c == 'i' || c == 'l' || c == 'o') {
|
||||
f.ignore(1);
|
||||
|
|
|
@ -1085,7 +1085,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
|
||||
// eval 1st expression
|
||||
AstNode *varbuf = init_ast->children[1]->clone();
|
||||
while (varbuf->simplify(true, false, false, stage, 32, true, false)) { }
|
||||
{
|
||||
int expr_width_hint = -1;
|
||||
bool expr_sign_hint = true;
|
||||
varbuf->detectSignWidth(expr_width_hint, expr_sign_hint);
|
||||
while (varbuf->simplify(true, false, false, stage, 32, true, false)) { }
|
||||
}
|
||||
|
||||
if (varbuf->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "Right hand side of 1st expression of generate for-loop is not constant!\n");
|
||||
|
@ -1107,7 +1112,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
{
|
||||
// eval 2nd expression
|
||||
AstNode *buf = while_ast->clone();
|
||||
while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
|
||||
{
|
||||
int expr_width_hint = -1;
|
||||
bool expr_sign_hint = true;
|
||||
buf->detectSignWidth(expr_width_hint, expr_sign_hint);
|
||||
while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, false)) { }
|
||||
}
|
||||
|
||||
if (buf->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "2nd expression of generate for-loop is not constant!\n");
|
||||
|
@ -1148,7 +1158,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
|
||||
// eval 3rd expression
|
||||
buf = next_ast->children[1]->clone();
|
||||
while (buf->simplify(true, false, false, stage, 32, true, false)) { }
|
||||
{
|
||||
int expr_width_hint = -1;
|
||||
bool expr_sign_hint = true;
|
||||
buf->detectSignWidth(expr_width_hint, expr_sign_hint);
|
||||
while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, true)) { }
|
||||
}
|
||||
|
||||
if (buf->type != AST_CONSTANT)
|
||||
log_file_error(filename, linenum, "Right hand side of 3rd expression of generate for-loop is not constant!\n");
|
||||
|
|
|
@ -295,6 +295,9 @@ int main(int argc, char **argv)
|
|||
printf(" -E <depsfile>\n");
|
||||
printf(" write a Makefile dependencies file with in- and output file names\n");
|
||||
printf("\n");
|
||||
printf(" -g\n");
|
||||
printf(" globally enable debug log messages\n");
|
||||
printf("\n");
|
||||
printf(" -V\n");
|
||||
printf(" print version information and exit\n");
|
||||
printf("\n");
|
||||
|
@ -315,7 +318,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "MXAQTVSm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:D:P:E:")) != -1)
|
||||
while ((opt = getopt(argc, argv, "MXAQTVSgm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:D:P:E:")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
|
@ -340,6 +343,9 @@ int main(int argc, char **argv)
|
|||
case 'S':
|
||||
passes_commands.push_back("synth");
|
||||
break;
|
||||
case 'g':
|
||||
log_force_debug++;
|
||||
break;
|
||||
case 'm':
|
||||
plugin_filenames.push_back(optarg);
|
||||
break;
|
||||
|
|
|
@ -56,6 +56,10 @@ int log_verbose_level;
|
|||
string log_last_error;
|
||||
void (*log_error_atexit)() = NULL;
|
||||
|
||||
int log_make_debug = 0;
|
||||
int log_force_debug = 0;
|
||||
int log_debug_suppressed = 0;
|
||||
|
||||
vector<int> header_count;
|
||||
pool<RTLIL::IdString> log_id_cache;
|
||||
vector<shared_str> string_buf;
|
||||
|
@ -92,6 +96,9 @@ void logv(const char *format, va_list ap)
|
|||
format++;
|
||||
}
|
||||
|
||||
if (log_make_debug && !ys_debug(1))
|
||||
return;
|
||||
|
||||
std::string str = vstringf(format, ap);
|
||||
|
||||
if (str.empty())
|
||||
|
|
43
kernel/log.h
43
kernel/log.h
|
@ -64,6 +64,10 @@ extern int log_verbose_level;
|
|||
extern string log_last_error;
|
||||
extern void (*log_error_atexit)();
|
||||
|
||||
extern int log_make_debug;
|
||||
extern int log_force_debug;
|
||||
extern int log_debug_suppressed;
|
||||
|
||||
void logv(const char *format, va_list ap);
|
||||
void logv_header(RTLIL::Design *design, const char *format, va_list ap);
|
||||
void logv_warning(const char *format, va_list ap);
|
||||
|
@ -82,6 +86,45 @@ YS_NORETURN void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf,
|
|||
void log_file_error(const string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4), noreturn);
|
||||
YS_NORETURN void log_cmd_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn);
|
||||
|
||||
#ifndef NDEBUG
|
||||
static inline bool ys_debug(int n = 0) { if (log_force_debug) return true; log_debug_suppressed += n; return false; }
|
||||
# define log_debug(...) do { if (ys_debug(1)) log(__VA_ARGS__); } while (0)
|
||||
#else
|
||||
static inline bool ys_debug(int n = 0) { return false; }
|
||||
# define log_debug(_fmt, ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
static inline void log_suppressed() {
|
||||
if (log_debug_suppressed && !log_make_debug) {
|
||||
log("<suppressed ~%d debug messages>\n", log_debug_suppressed);
|
||||
log_debug_suppressed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct LogMakeDebugHdl {
|
||||
bool status = false;
|
||||
LogMakeDebugHdl(bool start_on = false) {
|
||||
if (start_on)
|
||||
on();
|
||||
}
|
||||
~LogMakeDebugHdl() {
|
||||
off();
|
||||
}
|
||||
void on() {
|
||||
if (status) return;
|
||||
status=true;
|
||||
log_make_debug++;
|
||||
}
|
||||
void off_silent() {
|
||||
if (!status) return;
|
||||
status=false;
|
||||
log_make_debug--;
|
||||
}
|
||||
void off() {
|
||||
off_silent();
|
||||
}
|
||||
};
|
||||
|
||||
void log_spacer();
|
||||
void log_push();
|
||||
void log_pop();
|
||||
|
|
|
@ -87,6 +87,7 @@ Pass::pre_post_exec_state_t Pass::pre_execute()
|
|||
void Pass::post_execute(Pass::pre_post_exec_state_t state)
|
||||
{
|
||||
IdString::checkpoint();
|
||||
log_suppressed();
|
||||
|
||||
int64_t time_ns = PerformanceTimer::query() - state.begin_ns;
|
||||
runtime_ns += time_ns;
|
||||
|
|
|
@ -94,4 +94,38 @@ struct TracePass : public Pass {
|
|||
}
|
||||
} TracePass;
|
||||
|
||||
struct DebugPass : public Pass {
|
||||
DebugPass() : Pass("debug", "run command with debug log messages enabled") { }
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" debug cmd\n");
|
||||
log("\n");
|
||||
log("Execute the specified command with debug log messages enabled\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
{
|
||||
// .. parse options ..
|
||||
break;
|
||||
}
|
||||
|
||||
log_force_debug++;
|
||||
|
||||
try {
|
||||
std::vector<std::string> new_args(args.begin() + argidx, args.end());
|
||||
Pass::call(design, new_args);
|
||||
} catch (...) {
|
||||
log_force_debug--;
|
||||
throw;
|
||||
}
|
||||
|
||||
log_force_debug--;
|
||||
}
|
||||
} DebugPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
||||
|
|
|
@ -137,7 +137,7 @@ void rmunused_module_cells(Module *module, bool verbose)
|
|||
|
||||
for (auto cell : unused) {
|
||||
if (verbose)
|
||||
log(" removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str());
|
||||
log_debug(" removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str());
|
||||
module->design->scratchpad_set_bool("opt.did_something", true);
|
||||
module->remove(cell);
|
||||
count_rm_cells++;
|
||||
|
@ -326,7 +326,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
|
|||
for (auto wire : maybe_del_wires)
|
||||
if (!used_signals.check_any(RTLIL::SigSpec(wire))) {
|
||||
if (check_public_name(wire->name) && verbose) {
|
||||
log(" removing unused non-port wire %s.\n", wire->name.c_str());
|
||||
log_debug(" removing unused non-port wire %s.\n", wire->name.c_str());
|
||||
}
|
||||
del_wires.insert(wire);
|
||||
del_wires_count++;
|
||||
|
@ -336,7 +336,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
|
|||
count_rm_wires += del_wires.size();
|
||||
|
||||
if (verbose && del_wires_count > 0)
|
||||
log(" removed %d unused temporary wires.\n", del_wires_count);
|
||||
log_debug(" removed %d unused temporary wires.\n", del_wires_count);
|
||||
}
|
||||
|
||||
bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
|
||||
|
@ -399,7 +399,7 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
|
|||
}
|
||||
|
||||
if (verbose)
|
||||
log(" removing redundant init attribute on %s.\n", log_id(wire));
|
||||
log_debug(" removing redundant init attribute on %s.\n", log_id(wire));
|
||||
|
||||
wire->attributes.erase("\\init");
|
||||
did_something = true;
|
||||
|
@ -426,7 +426,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
|
|||
}
|
||||
for (auto cell : delcells) {
|
||||
if (verbose)
|
||||
log(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(),
|
||||
log_debug(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(),
|
||||
log_signal(cell->getPort("\\Y")), log_signal(cell->getPort("\\A")));
|
||||
module->remove(cell);
|
||||
}
|
||||
|
@ -551,6 +551,7 @@ struct CleanPass : public Pass {
|
|||
rmunused_module(module, purge_mode, false, false);
|
||||
}
|
||||
|
||||
log_suppressed();
|
||||
if (count_rm_cells > 0 || count_rm_wires > 0)
|
||||
log("Removed %d unused cells and %d unused wires.\n", count_rm_cells, count_rm_wires);
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
|
|||
if (sig.size() == 0)
|
||||
continue;
|
||||
|
||||
log("Setting undriven signal in %s to undef: %s\n", RTLIL::id2cstr(module->name), log_signal(c));
|
||||
log_debug("Setting undriven signal in %s to undef: %s\n", RTLIL::id2cstr(module->name), log_signal(c));
|
||||
module->connect(RTLIL::SigSig(c, RTLIL::SigSpec(RTLIL::State::Sx, c.width)));
|
||||
did_something = true;
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell,
|
|||
RTLIL::SigSpec Y = cell->getPort(out_port);
|
||||
out_val.extend_u0(Y.size(), false);
|
||||
|
||||
log("Replacing %s cell `%s' (%s) in module `%s' with constant driver `%s = %s'.\n",
|
||||
log_debug("Replacing %s cell `%s' (%s) in module `%s' with constant driver `%s = %s'.\n",
|
||||
cell->type.c_str(), cell->name.c_str(), info.c_str(),
|
||||
module->name.c_str(), log_signal(Y), log_signal(out_val));
|
||||
// log_cell(cell);
|
||||
|
@ -134,7 +134,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
|
|||
if (GetSize(grouped_bits[i]) == GetSize(bits_y))
|
||||
return false;
|
||||
|
||||
log("Replacing %s cell `%s' in module `%s' with cells using grouped bits:\n",
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with cells using grouped bits:\n",
|
||||
log_id(cell->type), log_id(cell), log_id(module));
|
||||
|
||||
for (int i = 0; i < GRP_N; i++)
|
||||
|
@ -156,7 +156,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
|
|||
}
|
||||
|
||||
if (cell->type.in("$and", "$or") && i == GRP_CONST_A) {
|
||||
log(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), log_id(cell->type), log_signal(new_a));
|
||||
log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), log_id(cell->type), log_signal(new_a));
|
||||
module->connect(new_y, new_b);
|
||||
module->connect(new_conn);
|
||||
continue;
|
||||
|
@ -180,10 +180,10 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
|
|||
|
||||
module->connect(new_conn);
|
||||
|
||||
log(" New cell `%s': A=%s", log_id(c), log_signal(new_a));
|
||||
log_debug(" New cell `%s': A=%s", log_id(c), log_signal(new_a));
|
||||
if (b_name == "\\B")
|
||||
log(", B=%s", log_signal(new_b));
|
||||
log("\n");
|
||||
log_debug(", B=%s", log_signal(new_b));
|
||||
log_debug("\n");
|
||||
}
|
||||
|
||||
cover_list("opt.opt_expr.fine.group", "$not", "$pos", "$and", "$or", "$xor", "$xnor", cell->type.str());
|
||||
|
@ -197,7 +197,7 @@ void handle_polarity_inv(Cell *cell, IdString port, IdString param, const SigMap
|
|||
{
|
||||
SigSpec sig = assign_map(cell->getPort(port));
|
||||
if (invert_map.count(sig)) {
|
||||
log("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n",
|
||||
log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n",
|
||||
log_id(port), log_id(cell->type), log_id(cell), log_id(cell->module),
|
||||
log_signal(sig), log_signal(invert_map.at(sig)));
|
||||
cell->setPort(port, (invert_map.at(sig)));
|
||||
|
@ -226,7 +226,7 @@ void handle_clkpol_celltype_swap(Cell *cell, string type1, string type2, IdStrin
|
|||
if (cell->type.in(type1, type2)) {
|
||||
SigSpec sig = assign_map(cell->getPort(port));
|
||||
if (invert_map.count(sig)) {
|
||||
log("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n",
|
||||
log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n",
|
||||
log_id(port), log_id(cell->type), log_id(cell), log_id(cell->module),
|
||||
log_signal(sig), log_signal(invert_map.at(sig)));
|
||||
cell->setPort(port, (invert_map.at(sig)));
|
||||
|
@ -455,9 +455,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
{
|
||||
if (cell->type == "$reduce_xnor") {
|
||||
cover("opt.opt_expr.reduce_xnor_not");
|
||||
log("Replacing %s cell `%s' in module `%s' with $not cell.\n",
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with $not cell.\n",
|
||||
log_id(cell->type), log_id(cell->name), log_id(module));
|
||||
cell->type = "$not";
|
||||
did_something = true;
|
||||
} else {
|
||||
cover("opt.opt_expr.unary_buffer");
|
||||
replace_cell(assign_map, module, cell, "unary_buffer", "\\Y", cell->getPort("\\A"));
|
||||
|
@ -488,7 +489,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
|
||||
if (GetSize(new_sig_a) < GetSize(sig_a)) {
|
||||
cover_list("opt.opt_expr.fine.neutral_A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_and", "$reduce_bool", cell->type.str());
|
||||
log("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
|
||||
log_debug("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
|
||||
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_sig_a));
|
||||
cell->setPort("\\A", new_sig_a);
|
||||
cell->parameters.at("\\A_WIDTH") = GetSize(new_sig_a);
|
||||
|
@ -511,7 +512,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
|
||||
if (GetSize(new_sig_b) < GetSize(sig_b)) {
|
||||
cover_list("opt.opt_expr.fine.neutral_B", "$logic_and", "$logic_or", cell->type.str());
|
||||
log("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
|
||||
log_debug("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
|
||||
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_sig_b));
|
||||
cell->setPort("\\B", new_sig_b);
|
||||
cell->parameters.at("\\B_WIDTH") = GetSize(new_sig_b);
|
||||
|
@ -537,7 +538,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
|
||||
if (new_a != RTLIL::State::Sm && RTLIL::SigSpec(new_a) != sig_a) {
|
||||
cover("opt.opt_expr.fine.$reduce_and");
|
||||
log("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
|
||||
log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
|
||||
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
|
||||
cell->setPort("\\A", sig_a = new_a);
|
||||
cell->parameters.at("\\A_WIDTH") = 1;
|
||||
|
@ -563,7 +564,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
|
||||
if (new_a != RTLIL::State::Sm && RTLIL::SigSpec(new_a) != sig_a) {
|
||||
cover_list("opt.opt_expr.fine.A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool", cell->type.str());
|
||||
log("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
|
||||
log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
|
||||
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
|
||||
cell->setPort("\\A", sig_a = new_a);
|
||||
cell->parameters.at("\\A_WIDTH") = 1;
|
||||
|
@ -589,7 +590,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
|
||||
if (new_b != RTLIL::State::Sm && RTLIL::SigSpec(new_b) != sig_b) {
|
||||
cover_list("opt.opt_expr.fine.B", "$logic_and", "$logic_or", cell->type.str());
|
||||
log("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
|
||||
log_debug("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
|
||||
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_b));
|
||||
cell->setPort("\\B", sig_b = new_b);
|
||||
cell->parameters.at("\\B_WIDTH") = 1;
|
||||
|
@ -640,7 +641,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
|
||||
if ((cell->type == "$_MUX_" || cell->type == "$mux") && invert_map.count(assign_map(cell->getPort("\\S"))) != 0) {
|
||||
cover_list("opt.opt_expr.invert.muxsel", "$_MUX_", "$mux", cell->type.str());
|
||||
log("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||
log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||
RTLIL::SigSpec tmp = cell->getPort("\\A");
|
||||
cell->setPort("\\A", cell->getPort("\\B"));
|
||||
cell->setPort("\\B", tmp);
|
||||
|
@ -750,7 +751,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
ACTION_DO("\\Y", cell->getPort("\\A"));
|
||||
if (input == State::S0 && !a.is_fully_undef()) {
|
||||
cover("opt.opt_expr.action_" S__LINE__);
|
||||
log("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n",
|
||||
log_debug("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n",
|
||||
cell->type.c_str(), cell->name.c_str(), module->name.c_str());
|
||||
cell->setPort("\\A", SigSpec(State::Sx, GetSize(a)));
|
||||
did_something = true;
|
||||
|
@ -822,7 +823,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
ACTION_DO("\\Y", cell->getPort("\\A"));
|
||||
} else {
|
||||
cover_list("opt.opt_expr.eqneq.isnot", "$eq", "$ne", cell->type.str());
|
||||
log("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||
cell->type = "$not";
|
||||
cell->parameters.erase("\\B_WIDTH");
|
||||
cell->parameters.erase("\\B_SIGNED");
|
||||
|
@ -837,7 +838,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
(assign_map(cell->getPort("\\A")).is_fully_zero() || assign_map(cell->getPort("\\B")).is_fully_zero()))
|
||||
{
|
||||
cover_list("opt.opt_expr.eqneq.cmpzero", "$eq", "$ne", cell->type.str());
|
||||
log("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell),
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell),
|
||||
log_id(module), "$eq" ? "$logic_not" : "$reduce_bool");
|
||||
cell->type = cell->type == "$eq" ? "$logic_not" : "$reduce_bool";
|
||||
if (assign_map(cell->getPort("\\A")).is_fully_zero()) {
|
||||
|
@ -876,7 +877,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
|
||||
cover_list("opt.opt_expr.constshift", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", cell->type.str());
|
||||
|
||||
log("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n",
|
||||
log_debug("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n",
|
||||
log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort("\\B"))), shift_bits, log_id(module), log_signal(sig_y));
|
||||
|
||||
module->connect(cell->getPort("\\Y"), sig_y);
|
||||
|
@ -939,7 +940,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
if (identity_wrt_b)
|
||||
cover_list("opt.opt_expr.identwrt.b", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str());
|
||||
|
||||
log("Replacing %s cell `%s' in module `%s' with identity for port %c.\n",
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with identity for port %c.\n",
|
||||
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B');
|
||||
|
||||
if (!identity_wrt_a) {
|
||||
|
@ -969,7 +970,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
if (mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") &&
|
||||
cell->getPort("\\A") == RTLIL::SigSpec(1, 1) && cell->getPort("\\B") == RTLIL::SigSpec(0, 1)) {
|
||||
cover_list("opt.opt_expr.mux_invert", "$mux", "$_MUX_", cell->type.str());
|
||||
log("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||
cell->setPort("\\A", cell->getPort("\\S"));
|
||||
cell->unsetPort("\\B");
|
||||
cell->unsetPort("\\S");
|
||||
|
@ -988,7 +989,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
|
||||
if (consume_x && mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\A") == RTLIL::SigSpec(0, 1)) {
|
||||
cover_list("opt.opt_expr.mux_and", "$mux", "$_MUX_", cell->type.str());
|
||||
log("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||
cell->setPort("\\A", cell->getPort("\\S"));
|
||||
cell->unsetPort("\\S");
|
||||
if (cell->type == "$mux") {
|
||||
|
@ -1008,7 +1009,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
|
||||
if (consume_x && mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\B") == RTLIL::SigSpec(1, 1)) {
|
||||
cover_list("opt.opt_expr.mux_or", "$mux", "$_MUX_", cell->type.str());
|
||||
log("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||
cell->setPort("\\B", cell->getPort("\\S"));
|
||||
cell->unsetPort("\\S");
|
||||
if (cell->type == "$mux") {
|
||||
|
@ -1061,7 +1062,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
}
|
||||
if (cell->getPort("\\S").size() != new_s.size()) {
|
||||
cover_list("opt.opt_expr.mux_reduce", "$mux", "$pmux", cell->type.str());
|
||||
log("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n",
|
||||
log_debug("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n",
|
||||
GetSize(cell->getPort("\\S")) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module));
|
||||
cell->setPort("\\A", new_a);
|
||||
cell->setPort("\\B", new_b);
|
||||
|
@ -1179,7 +1180,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
{
|
||||
cover("opt.opt_expr.mul_shift.zero");
|
||||
|
||||
log("Replacing multiply-by-zero cell `%s' in module `%s' with zero-driver.\n",
|
||||
log_debug("Replacing multiply-by-zero cell `%s' in module `%s' with zero-driver.\n",
|
||||
cell->name.c_str(), module->name.c_str());
|
||||
|
||||
module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
|
||||
|
@ -1197,7 +1198,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
else
|
||||
cover("opt.opt_expr.mul_shift.unswapped");
|
||||
|
||||
log("Replacing multiply-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
|
||||
log_debug("Replacing multiply-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
|
||||
a_val, cell->name.c_str(), module->name.c_str(), i);
|
||||
|
||||
if (!swapped_ab) {
|
||||
|
@ -1237,7 +1238,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
{
|
||||
cover("opt.opt_expr.divmod_zero");
|
||||
|
||||
log("Replacing divide-by-zero cell `%s' in module `%s' with undef-driver.\n",
|
||||
log_debug("Replacing divide-by-zero cell `%s' in module `%s' with undef-driver.\n",
|
||||
cell->name.c_str(), module->name.c_str());
|
||||
|
||||
module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(State::Sx, sig_y.size())));
|
||||
|
@ -1254,7 +1255,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
{
|
||||
cover("opt.opt_expr.div_shift");
|
||||
|
||||
log("Replacing divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
|
||||
log_debug("Replacing divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
|
||||
b_val, cell->name.c_str(), module->name.c_str(), i);
|
||||
|
||||
std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(i, 6);
|
||||
|
@ -1272,7 +1273,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
{
|
||||
cover("opt.opt_expr.mod_mask");
|
||||
|
||||
log("Replacing modulo-by-%d cell `%s' in module `%s' with bitmask.\n",
|
||||
log_debug("Replacing modulo-by-%d cell `%s' in module `%s' with bitmask.\n",
|
||||
b_val, cell->name.c_str(), module->name.c_str());
|
||||
|
||||
std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(State::S1, i);
|
||||
|
@ -1342,7 +1343,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
SigSpec y_sig = cell->getPort("\\Y");
|
||||
Const y_value(cell->type.in("$eq", "$eqx") ? 0 : 1, GetSize(y_sig));
|
||||
|
||||
log("Replacing cell `%s' in module `%s' with constant driver %s.\n",
|
||||
log_debug("Replacing cell `%s' in module `%s' with constant driver %s.\n",
|
||||
log_id(cell), log_id(module), log_signal(y_value));
|
||||
|
||||
module->connect(y_sig, y_value);
|
||||
|
@ -1354,7 +1355,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
|
||||
if (redundant_bits)
|
||||
{
|
||||
log("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n",
|
||||
log_debug("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n",
|
||||
redundant_bits, log_id(cell->type), log_id(cell), log_id(module));
|
||||
|
||||
cell->setPort("\\A", sig_a);
|
||||
|
@ -1493,7 +1494,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
|
||||
if (replace || remove)
|
||||
{
|
||||
log("Replacing %s cell `%s' (implementing %s) with %s.\n",
|
||||
log_debug("Replacing %s cell `%s' (implementing %s) with %s.\n",
|
||||
log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str());
|
||||
if (replace)
|
||||
module->connect(cell->getPort("\\Y"), replace_sig);
|
||||
|
@ -1599,8 +1600,14 @@ struct OptExprPass : public Pass {
|
|||
|
||||
for (auto module : design->selected_modules())
|
||||
{
|
||||
if (undriven)
|
||||
log("Optimizing module %s.\n", log_id(module));
|
||||
|
||||
if (undriven) {
|
||||
did_something = false;
|
||||
replace_undriven(design, module);
|
||||
if (did_something)
|
||||
design->scratchpad_set_bool("opt.did_something", true);
|
||||
}
|
||||
|
||||
do {
|
||||
do {
|
||||
|
@ -1610,7 +1617,11 @@ struct OptExprPass : public Pass {
|
|||
design->scratchpad_set_bool("opt.did_something", true);
|
||||
} while (did_something);
|
||||
replace_const_cells(design, module, true, mux_undef, mux_bool, do_fine, keepdc, clkinv);
|
||||
if (did_something)
|
||||
design->scratchpad_set_bool("opt.did_something", true);
|
||||
} while (did_something);
|
||||
|
||||
log_suppressed();
|
||||
}
|
||||
|
||||
log_pop();
|
||||
|
|
|
@ -315,17 +315,17 @@ struct OptMergeWorker
|
|||
{
|
||||
if (sharemap.count(cell) > 0) {
|
||||
did_something = true;
|
||||
log(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), sharemap[cell]->name.c_str());
|
||||
log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), sharemap[cell]->name.c_str());
|
||||
for (auto &it : cell->connections()) {
|
||||
if (cell->output(it.first)) {
|
||||
RTLIL::SigSpec other_sig = sharemap[cell]->getPort(it.first);
|
||||
log(" Redirecting output %s: %s = %s\n", it.first.c_str(),
|
||||
log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(),
|
||||
log_signal(it.second), log_signal(other_sig));
|
||||
module->connect(RTLIL::SigSig(it.second, other_sig));
|
||||
assign_map.add(it.second, other_sig);
|
||||
}
|
||||
}
|
||||
log(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str());
|
||||
log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str());
|
||||
#ifdef USE_CELL_HASH_CACHE
|
||||
cell_hash_cache.erase(cell);
|
||||
#endif
|
||||
|
@ -336,6 +336,8 @@ struct OptMergeWorker
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
log_suppressed();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -181,14 +181,14 @@ struct OptMuxtreeWorker
|
|||
|
||||
for (int mux_idx = 0; mux_idx < GetSize(root_muxes); mux_idx++)
|
||||
if (root_muxes.at(mux_idx)) {
|
||||
log(" Root of a mux tree: %s%s\n", log_id(mux2info[mux_idx].cell), root_enable_muxes.at(mux_idx) ? " (pure)" : "");
|
||||
log_debug(" Root of a mux tree: %s%s\n", log_id(mux2info[mux_idx].cell), root_enable_muxes.at(mux_idx) ? " (pure)" : "");
|
||||
root_mux_rerun.erase(mux_idx);
|
||||
eval_root_mux(mux_idx);
|
||||
}
|
||||
|
||||
while (!root_mux_rerun.empty()) {
|
||||
int mux_idx = *root_mux_rerun.begin();
|
||||
log(" Root of a mux tree: %s (rerun as non-pure)\n", log_id(mux2info[mux_idx].cell));
|
||||
log_debug(" Root of a mux tree: %s (rerun as non-pure)\n", log_id(mux2info[mux_idx].cell));
|
||||
log_assert(root_enable_muxes.at(mux_idx));
|
||||
root_mux_rerun.erase(mux_idx);
|
||||
eval_root_mux(mux_idx);
|
||||
|
@ -326,7 +326,7 @@ struct OptMuxtreeWorker
|
|||
if (abort_count == 0) {
|
||||
root_mux_rerun.insert(m);
|
||||
root_enable_muxes.at(m) = true;
|
||||
log(" Removing pure flag from root mux %s.\n", log_id(mux2info[m].cell));
|
||||
log_debug(" Removing pure flag from root mux %s.\n", log_id(mux2info[m].cell));
|
||||
} else
|
||||
eval_mux(knowledge, m, false, do_enable_ports, abort_count - 1);
|
||||
} else
|
||||
|
|
|
@ -369,6 +369,7 @@ struct Pmux2ShiftxPass : public Pass {
|
|||
|
||||
dict<SigSpec, pool<int>> seldb;
|
||||
|
||||
SigSpec A = cell->getPort("\\A");
|
||||
SigSpec B = cell->getPort("\\B");
|
||||
SigSpec S = sigmap(cell->getPort("\\S"));
|
||||
for (int i = 0; i < GetSize(S); i++)
|
||||
|
@ -419,6 +420,8 @@ struct Pmux2ShiftxPass : public Pass {
|
|||
choices[val] = i;
|
||||
}
|
||||
|
||||
bool full_pmux = GetSize(choices) == GetSize(S);
|
||||
|
||||
// TBD: also find choices that are using signals that are subsets of the bits in "sig"
|
||||
|
||||
if (!verbose)
|
||||
|
@ -634,7 +637,21 @@ struct Pmux2ShiftxPass : public Pass {
|
|||
log(" range density: %d%%\n", range_density);
|
||||
log(" absolute density: %d%%\n", absolute_density);
|
||||
|
||||
bool full_case = (min_choice == 0) && (max_choice == (1 << GetSize(sig))-1) && (max_choice+1 == GetSize(choices));
|
||||
if (full_pmux) {
|
||||
int full_density = 100*GetSize(choices) / (1 << GetSize(sig));
|
||||
log(" full density: %d%%\n", full_density);
|
||||
if (full_density < min_density) {
|
||||
full_pmux = false;
|
||||
} else {
|
||||
min_choice = 0;
|
||||
max_choice = (1 << GetSize(sig))-1;
|
||||
log(" update to full case.\n");
|
||||
log(" new min choice: %d\n", min_choice);
|
||||
log(" new max choice: %d\n", max_choice);
|
||||
}
|
||||
}
|
||||
|
||||
bool full_case = (min_choice == 0) && (max_choice == (1 << GetSize(sig))-1) && (full_pmux || max_choice+1 == GetSize(choices));
|
||||
log(" full case: %s\n", full_case ? "true" : "false");
|
||||
|
||||
// check density percentages
|
||||
|
@ -677,6 +694,10 @@ struct Pmux2ShiftxPass : public Pass {
|
|||
|
||||
// create data signal
|
||||
SigSpec data(State::Sx, (max_choice+1)*extwidth);
|
||||
if (full_pmux) {
|
||||
for (int i = 0; i <= max_choice; i++)
|
||||
data.replace(i*extwidth, A);
|
||||
}
|
||||
for (auto &it : perm_choices) {
|
||||
int position = it.first.as_int()*extwidth;
|
||||
int data_index = it.second;
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
#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; &fraig; &scorr; &dc2; &retime; &dch -f; &if; &mfs"
|
||||
//#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_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"
|
||||
|
||||
|
@ -343,7 +344,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
|||
else
|
||||
abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str());
|
||||
|
||||
abc_script += stringf("&read %s/input.xaig; &ps ", tempdir_name.c_str());
|
||||
abc_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str());
|
||||
|
||||
if (!script_file.empty()) {
|
||||
if (script_file[0] == '+') {
|
||||
|
@ -1401,6 +1402,9 @@ struct Abc9Pass : public Pass {
|
|||
|
||||
for (auto mod : design->selected_modules())
|
||||
{
|
||||
if (mod->attributes.count("\\abc_box_id"))
|
||||
continue;
|
||||
|
||||
if (mod->processes.size() > 0) {
|
||||
log("Skipping module %s as it contains processes.\n", log_id(mod));
|
||||
continue;
|
||||
|
|
|
@ -72,6 +72,8 @@ struct TechmapWorker
|
|||
pool<IdString> flatten_done_list;
|
||||
pool<Cell*> flatten_keep_list;
|
||||
|
||||
pool<string> log_msg_cache;
|
||||
|
||||
struct TechmapWireData {
|
||||
RTLIL::Wire *wire;
|
||||
RTLIL::SigSpec value;
|
||||
|
@ -390,6 +392,7 @@ struct TechmapWorker
|
|||
|
||||
bool log_continue = false;
|
||||
bool did_something = false;
|
||||
LogMakeDebugHdl mkdebug;
|
||||
|
||||
SigMap sigmap(module);
|
||||
|
||||
|
@ -547,6 +550,7 @@ struct TechmapWorker
|
|||
if (extmapper_name == "wrap") {
|
||||
std::string cmd_string = tpl->attributes.at("\\techmap_wrap").decode_string();
|
||||
log("Running \"%s\" on wrapper %s.\n", cmd_string.c_str(), log_id(extmapper_module));
|
||||
mkdebug.on();
|
||||
Pass::call_on_module(extmapper_design, extmapper_module, cmd_string);
|
||||
log_continue = true;
|
||||
}
|
||||
|
@ -560,11 +564,21 @@ struct TechmapWorker
|
|||
goto use_wrapper_tpl;
|
||||
}
|
||||
|
||||
log("%s %s.%s (%s) to %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module));
|
||||
auto msg = stringf("Using extmapper %s for cells of type %s.", log_id(extmapper_module), log_id(cell->type));
|
||||
if (!log_msg_cache.count(msg)) {
|
||||
log_msg_cache.insert(msg);
|
||||
log("%s\n", msg.c_str());
|
||||
}
|
||||
log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module));
|
||||
}
|
||||
else
|
||||
{
|
||||
log("%s %s.%s (%s) with %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), extmapper_name.c_str());
|
||||
auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_name.c_str(), log_id(cell->type));
|
||||
if (!log_msg_cache.count(msg)) {
|
||||
log_msg_cache.insert(msg);
|
||||
log("%s\n", msg.c_str());
|
||||
}
|
||||
log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), extmapper_name.c_str());
|
||||
|
||||
if (extmapper_name == "simplemap") {
|
||||
if (simplemap_mappers.count(cell->type) == 0)
|
||||
|
@ -662,6 +676,7 @@ struct TechmapWorker
|
|||
tpl = techmap_cache[key];
|
||||
} else {
|
||||
if (parameters.size() != 0) {
|
||||
mkdebug.on();
|
||||
derived_name = tpl->derive(map, dict<RTLIL::IdString, RTLIL::Const>(parameters.begin(), parameters.end()));
|
||||
tpl = map->module(derived_name);
|
||||
log_continue = true;
|
||||
|
@ -831,6 +846,7 @@ struct TechmapWorker
|
|||
if (log_continue) {
|
||||
log_header(design, "Continuing TECHMAP pass.\n");
|
||||
log_continue = false;
|
||||
mkdebug.off();
|
||||
}
|
||||
while (techmap_module(map, tpl, map, handled_cells, celltypeMap, true)) { }
|
||||
}
|
||||
|
@ -842,6 +858,7 @@ struct TechmapWorker
|
|||
if (log_continue) {
|
||||
log_header(design, "Continuing TECHMAP pass.\n");
|
||||
log_continue = false;
|
||||
mkdebug.off();
|
||||
}
|
||||
|
||||
if (extern_mode && !in_recursion)
|
||||
|
@ -861,13 +878,18 @@ struct TechmapWorker
|
|||
module_queue.insert(m);
|
||||
}
|
||||
|
||||
log("%s %s.%s to imported %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(m_name));
|
||||
log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(m_name));
|
||||
cell->type = m_name;
|
||||
cell->parameters.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
log("%s %s.%s using %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(tpl));
|
||||
auto msg = stringf("Using template %s for cells of type %s.", log_id(tpl), log_id(cell->type));
|
||||
if (!log_msg_cache.count(msg)) {
|
||||
log_msg_cache.insert(msg);
|
||||
log("%s\n", msg.c_str());
|
||||
}
|
||||
log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(tpl));
|
||||
techmap_module_worker(design, module, cell, tpl);
|
||||
cell = NULL;
|
||||
}
|
||||
|
@ -885,6 +907,7 @@ struct TechmapWorker
|
|||
if (log_continue) {
|
||||
log_header(design, "Continuing TECHMAP pass.\n");
|
||||
log_continue = false;
|
||||
mkdebug.off();
|
||||
}
|
||||
|
||||
return did_something;
|
||||
|
@ -1085,7 +1108,7 @@ struct TechmapPass : public Pass {
|
|||
if (map_files.empty()) {
|
||||
std::istringstream f(stdcells_code);
|
||||
Frontend::frontend_call(map, &f, "<techmap.v>", verilog_frontend);
|
||||
} else
|
||||
} else {
|
||||
for (auto &fn : map_files)
|
||||
if (fn.substr(0, 1) == "%") {
|
||||
if (!saved_designs.count(fn.substr(1))) {
|
||||
|
@ -1104,6 +1127,9 @@ struct TechmapPass : public Pass {
|
|||
log_cmd_error("Can't open map file `%s'\n", fn.c_str());
|
||||
Frontend::frontend_call(map, &f, fn, (fn.size() > 3 && fn.substr(fn.size()-3) == ".il") ? "ilang" : verilog_frontend);
|
||||
}
|
||||
}
|
||||
|
||||
log_header(design, "Continuing TECHMAP pass.\n");
|
||||
|
||||
std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> celltypeMap;
|
||||
for (auto &it : map->modules_) {
|
||||
|
@ -1211,6 +1237,7 @@ struct FlattenPass : public Pass {
|
|||
}
|
||||
}
|
||||
|
||||
log_suppressed();
|
||||
log("No more expansions possible.\n");
|
||||
|
||||
if (top_mod != NULL)
|
||||
|
|
|
@ -28,6 +28,12 @@ $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v))
|
|||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v))
|
||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt))
|
||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v))
|
||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_hx.box))
|
||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_hx.lut))
|
||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_lp.box))
|
||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_lp.lut))
|
||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_u.box))
|
||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_u.lut))
|
||||
|
||||
$(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init1.vh))
|
||||
$(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init2.vh))
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_hx8k.txt
|
||||
|
||||
# NB: Inputs/Outputs must be ordered alphabetically
|
||||
|
||||
# Inputs: C D
|
||||
# Outputs: Q
|
||||
SB_DFF 1 1 2 1
|
||||
- -
|
||||
|
||||
# Inputs: C D E
|
||||
# Outputs: Q
|
||||
SB_DFFE 2 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D R
|
||||
# Outputs: Q
|
||||
SB_DFFSR 3 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D R
|
||||
# Outputs: Q
|
||||
SB_DFFR 4 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D S
|
||||
# Outputs: Q
|
||||
SB_DFFSS 5 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D S
|
||||
# Outputs: Q
|
||||
SB_DFFS 6 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D E R
|
||||
# Outputs: Q
|
||||
SB_DFFESR 7 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E R
|
||||
# Outputs: Q
|
||||
SB_DFFER 8 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E S
|
||||
# Outputs: Q
|
||||
SB_DFFESS 9 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E S
|
||||
# Outputs: Q
|
||||
SB_DFFES 10 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D
|
||||
# Outputs: Q
|
||||
SB_DFFN 11 0 2 1
|
||||
- -
|
||||
|
||||
# Inputs: C D E
|
||||
# Outputs: Q
|
||||
SB_DFFNE 12 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D R
|
||||
# Outputs: Q
|
||||
SB_DFFNSR 13 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D R
|
||||
# Outputs: Q
|
||||
SB_DFFNR 14 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D S
|
||||
# Outputs: Q
|
||||
SB_DFFNSS 15 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D S
|
||||
# Outputs: Q
|
||||
SB_DFFNS 16 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D E R
|
||||
# Outputs: Q
|
||||
SB_DFFNESR 17 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E R
|
||||
# Outputs: Q
|
||||
SB_DFFNER 18 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E S
|
||||
# Outputs: Q
|
||||
SB_DFFNESS 19 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E S
|
||||
# Outputs: Q
|
||||
SB_DFFNES 20 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: CI I0 I1
|
||||
# Outputs: CO
|
||||
SB_CARRY 21 1 3 1
|
||||
126 259 231
|
||||
|
||||
# Inputs: I0 I1 I2 I3
|
||||
# Outputs: O
|
||||
SB_LUT4 22 0 4 1
|
||||
449 400 379 316
|
|
@ -0,0 +1,6 @@
|
|||
# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_hx8k.txt
|
||||
# I3 I2 I1 I0
|
||||
1 1 316
|
||||
2 1 316 379
|
||||
3 1 316 379 400
|
||||
4 1 316 379 400 449
|
|
@ -0,0 +1,113 @@
|
|||
# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_lp8k.txt
|
||||
|
||||
# NB: Inputs/Outputs must be ordered alphabetically
|
||||
|
||||
# Inputs: C D
|
||||
# Outputs: Q
|
||||
SB_DFF 1 1 2 1
|
||||
- -
|
||||
|
||||
# Inputs: C D E
|
||||
# Outputs: Q
|
||||
SB_DFFE 2 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D R
|
||||
# Outputs: Q
|
||||
SB_DFFSR 3 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D R
|
||||
# Outputs: Q
|
||||
SB_DFFR 4 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D S
|
||||
# Outputs: Q
|
||||
SB_DFFSS 5 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D S
|
||||
# Outputs: Q
|
||||
SB_DFFS 6 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D E R
|
||||
# Outputs: Q
|
||||
SB_DFFESR 7 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E R
|
||||
# Outputs: Q
|
||||
SB_DFFER 8 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E S
|
||||
# Outputs: Q
|
||||
SB_DFFESS 9 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E S
|
||||
# Outputs: Q
|
||||
SB_DFFES 10 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D
|
||||
# Outputs: Q
|
||||
SB_DFFN 11 0 2 1
|
||||
- -
|
||||
|
||||
# Inputs: C D E
|
||||
# Outputs: Q
|
||||
SB_DFFNE 12 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D R
|
||||
# Outputs: Q
|
||||
SB_DFFNSR 13 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D R
|
||||
# Outputs: Q
|
||||
SB_DFFNR 14 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D S
|
||||
# Outputs: Q
|
||||
SB_DFFNSS 15 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D S
|
||||
# Outputs: Q
|
||||
SB_DFFNS 16 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D E R
|
||||
# Outputs: Q
|
||||
SB_DFFNESR 17 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E R
|
||||
# Outputs: Q
|
||||
SB_DFFNER 18 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E S
|
||||
# Outputs: Q
|
||||
SB_DFFNESS 19 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E S
|
||||
# Outputs: Q
|
||||
SB_DFFNES 20 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: CI I0 I1
|
||||
# Outputs: CO
|
||||
SB_CARRY 21 1 3 1
|
||||
186 675 609
|
||||
|
||||
# Inputs: I0 I1 I2 I3
|
||||
# Outputs: O
|
||||
SB_LUT4 22 0 4 1
|
||||
465 558 589 661
|
|
@ -0,0 +1,6 @@
|
|||
# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_lp8k.txt
|
||||
# I3 I2 I1 I0
|
||||
1 1 465
|
||||
2 1 465 558
|
||||
3 1 465 558 589
|
||||
4 1 465 558 589 661
|
|
@ -0,0 +1,113 @@
|
|||
# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_up5k.txt
|
||||
|
||||
# NB: Inputs/Outputs must be ordered alphabetically
|
||||
|
||||
# Inputs: C D
|
||||
# Outputs: Q
|
||||
SB_DFF 1 1 2 1
|
||||
- -
|
||||
|
||||
# Inputs: C D E
|
||||
# Outputs: Q
|
||||
SB_DFFE 2 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D R
|
||||
# Outputs: Q
|
||||
SB_DFFSR 3 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D R
|
||||
# Outputs: Q
|
||||
SB_DFFR 4 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D S
|
||||
# Outputs: Q
|
||||
SB_DFFSS 5 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D S
|
||||
# Outputs: Q
|
||||
SB_DFFS 6 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D E R
|
||||
# Outputs: Q
|
||||
SB_DFFESR 7 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E R
|
||||
# Outputs: Q
|
||||
SB_DFFER 8 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E S
|
||||
# Outputs: Q
|
||||
SB_DFFESS 9 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E S
|
||||
# Outputs: Q
|
||||
SB_DFFES 10 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D
|
||||
# Outputs: Q
|
||||
SB_DFFN 11 0 2 1
|
||||
- -
|
||||
|
||||
# Inputs: C D E
|
||||
# Outputs: Q
|
||||
SB_DFFNE 12 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D R
|
||||
# Outputs: Q
|
||||
SB_DFFNSR 13 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D R
|
||||
# Outputs: Q
|
||||
SB_DFFNR 14 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D S
|
||||
# Outputs: Q
|
||||
SB_DFFNSS 15 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D S
|
||||
# Outputs: Q
|
||||
SB_DFFNS 16 0 3 1
|
||||
- - -
|
||||
|
||||
# Inputs: C D E R
|
||||
# Outputs: Q
|
||||
SB_DFFNESR 17 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E R
|
||||
# Outputs: Q
|
||||
SB_DFFNER 18 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E S
|
||||
# Outputs: Q
|
||||
SB_DFFNESS 19 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: C D E S
|
||||
# Outputs: Q
|
||||
SB_DFFNES 20 0 4 1
|
||||
- - - -
|
||||
|
||||
# Inputs: CI I0 I1
|
||||
# Outputs: CO
|
||||
SB_CARRY 21 1 3 1
|
||||
278 675 609
|
||||
|
||||
# Inputs: I0 I1 I2 I3
|
||||
# Outputs: O
|
||||
SB_LUT4 22 0 4 1
|
||||
1285 1231 1205 874
|
|
@ -0,0 +1,6 @@
|
|||
# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_up5k.txt
|
||||
# I3 I2 I1 I0
|
||||
1 1 874
|
||||
2 1 874 1205
|
||||
3 1 874 1205 1231
|
||||
4 1 874 1205 1231 1285
|
|
@ -37,20 +37,24 @@ module \$lut (A, Y);
|
|||
|
||||
generate
|
||||
if (WIDTH == 1) begin
|
||||
SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
||||
.I0(A[0]), .I1(1'b0), .I2(1'b0), .I3(1'b0));
|
||||
localparam [15:0] INIT = {{8{LUT[1]}}, {8{LUT[0]}}};
|
||||
SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
|
||||
.I0(1'b0), .I1(1'b0), .I2(1'b0), .I3(A[0]));
|
||||
end else
|
||||
if (WIDTH == 2) begin
|
||||
SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
||||
.I0(A[0]), .I1(A[1]), .I2(1'b0), .I3(1'b0));
|
||||
localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[1]}}, {4{LUT[2]}}, {4{LUT[0]}}};
|
||||
SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
|
||||
.I0(1'b0), .I1(1'b0), .I2(A[1]), .I3(A[0]));
|
||||
end else
|
||||
if (WIDTH == 3) begin
|
||||
SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
||||
.I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(1'b0));
|
||||
localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[3]}}, {2{LUT[5]}}, {2{LUT[1]}}, {2{LUT[6]}}, {2{LUT[2]}}, {2{LUT[4]}}, {2{LUT[0]}}};
|
||||
SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
|
||||
.I0(1'b0), .I1(A[2]), .I2(A[1]), .I3(A[0]));
|
||||
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),
|
||||
.I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]));
|
||||
.I0(A[3]), .I1(A[2]), .I2(A[1]), .I3(A[0]));
|
||||
end else begin
|
||||
wire _TECHMAP_FAIL_ = 1;
|
||||
end
|
||||
|
|
|
@ -127,6 +127,7 @@ endmodule
|
|||
|
||||
// SiliconBlue Logic Cells
|
||||
|
||||
(* abc_box_id = 22 *)
|
||||
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];
|
||||
|
@ -135,24 +136,32 @@ 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);
|
||||
assign CO = (I0 && I1) || ((I0 || I1) && CI);
|
||||
endmodule
|
||||
|
||||
// Positive Edge SiliconBlue FF Cells
|
||||
|
||||
module SB_DFF (output `SB_DFF_REG, input C, D);
|
||||
(* 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
|
||||
always @(posedge C)
|
||||
Q <= D;
|
||||
`else
|
||||
always @* Q = D;
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
module SB_DFFE (output `SB_DFF_REG, input C, E, D);
|
||||
//(* abc_box_id = 2, abc_flop *)
|
||||
module SB_DFFE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, (* abc_flop_d *) input D);
|
||||
always @(posedge C)
|
||||
if (E)
|
||||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFSR (output `SB_DFF_REG, input C, R, D);
|
||||
//(* abc_box_id = 3, abc_flop *)
|
||||
module SB_DFFSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
|
||||
always @(posedge C)
|
||||
if (R)
|
||||
Q <= 0;
|
||||
|
@ -160,7 +169,8 @@ module SB_DFFSR (output `SB_DFF_REG, input C, R, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFR (output `SB_DFF_REG, input C, R, D);
|
||||
//(* abc_box_id = 4, abc_flop *)
|
||||
module SB_DFFR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
|
||||
always @(posedge C, posedge R)
|
||||
if (R)
|
||||
Q <= 0;
|
||||
|
@ -168,7 +178,8 @@ module SB_DFFR (output `SB_DFF_REG, input C, R, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFSS (output `SB_DFF_REG, input C, S, D);
|
||||
//(* abc_box_id = 5, abc_flop *)
|
||||
module SB_DFFSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
|
||||
always @(posedge C)
|
||||
if (S)
|
||||
Q <= 1;
|
||||
|
@ -176,7 +187,8 @@ module SB_DFFSS (output `SB_DFF_REG, input C, S, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFS (output `SB_DFF_REG, input C, S, D);
|
||||
//(* abc_box_id = 6, abc_flop *)
|
||||
module SB_DFFS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
|
||||
always @(posedge C, posedge S)
|
||||
if (S)
|
||||
Q <= 1;
|
||||
|
@ -184,7 +196,8 @@ module SB_DFFS (output `SB_DFF_REG, input C, S, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D);
|
||||
//(* abc_box_id = 7, abc_flop *)
|
||||
module SB_DFFESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
|
||||
always @(posedge C)
|
||||
if (E) begin
|
||||
if (R)
|
||||
|
@ -194,7 +207,8 @@ module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D);
|
|||
end
|
||||
endmodule
|
||||
|
||||
module SB_DFFER (output `SB_DFF_REG, input C, E, R, D);
|
||||
//(* abc_box_id = 8, abc_flop *)
|
||||
module SB_DFFER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
|
||||
always @(posedge C, posedge R)
|
||||
if (R)
|
||||
Q <= 0;
|
||||
|
@ -202,7 +216,8 @@ module SB_DFFER (output `SB_DFF_REG, input C, E, R, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D);
|
||||
//(* abc_box_id = 9, abc_flop *)
|
||||
module SB_DFFESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
|
||||
always @(posedge C)
|
||||
if (E) begin
|
||||
if (S)
|
||||
|
@ -212,7 +227,8 @@ module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D);
|
|||
end
|
||||
endmodule
|
||||
|
||||
module SB_DFFES (output `SB_DFF_REG, input C, E, S, D);
|
||||
//(* abc_box_id = 10, abc_flop *)
|
||||
module SB_DFFES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
|
||||
always @(posedge C, posedge S)
|
||||
if (S)
|
||||
Q <= 1;
|
||||
|
@ -222,18 +238,21 @@ endmodule
|
|||
|
||||
// Negative Edge SiliconBlue FF Cells
|
||||
|
||||
module SB_DFFN (output `SB_DFF_REG, input C, D);
|
||||
//(* abc_box_id = 11, abc_flop *)
|
||||
module SB_DFFN ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D);
|
||||
always @(negedge C)
|
||||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFNE (output `SB_DFF_REG, input C, E, D);
|
||||
//(* abc_box_id = 12, abc_flop *)
|
||||
module SB_DFFNE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, (* abc_flop_d *) input D);
|
||||
always @(negedge C)
|
||||
if (E)
|
||||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFNSR (output `SB_DFF_REG, input C, R, D);
|
||||
//(* abc_box_id = 13, abc_flop *)
|
||||
module SB_DFFNSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
|
||||
always @(negedge C)
|
||||
if (R)
|
||||
Q <= 0;
|
||||
|
@ -241,7 +260,8 @@ module SB_DFFNSR (output `SB_DFF_REG, input C, R, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFNR (output `SB_DFF_REG, input C, R, D);
|
||||
//(* abc_box_id = 14, abc_flop *)
|
||||
module SB_DFFNR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
|
||||
always @(negedge C, posedge R)
|
||||
if (R)
|
||||
Q <= 0;
|
||||
|
@ -249,7 +269,8 @@ module SB_DFFNR (output `SB_DFF_REG, input C, R, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFNSS (output `SB_DFF_REG, input C, S, D);
|
||||
//(* abc_box_id = 15, abc_flop *)
|
||||
module SB_DFFNSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
|
||||
always @(negedge C)
|
||||
if (S)
|
||||
Q <= 1;
|
||||
|
@ -257,7 +278,8 @@ module SB_DFFNSS (output `SB_DFF_REG, input C, S, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFNS (output `SB_DFF_REG, input C, S, D);
|
||||
//(* abc_box_id = 16, abc_flop *)
|
||||
module SB_DFFNS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
|
||||
always @(negedge C, posedge S)
|
||||
if (S)
|
||||
Q <= 1;
|
||||
|
@ -265,7 +287,8 @@ module SB_DFFNS (output `SB_DFF_REG, input C, S, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D);
|
||||
//(* abc_box_id = 17, abc_flop *)
|
||||
module SB_DFFNESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
|
||||
always @(negedge C)
|
||||
if (E) begin
|
||||
if (R)
|
||||
|
@ -275,7 +298,8 @@ module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D);
|
|||
end
|
||||
endmodule
|
||||
|
||||
module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D);
|
||||
//(* abc_box_id = 18, abc_flop *)
|
||||
module SB_DFFNER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
|
||||
always @(negedge C, posedge R)
|
||||
if (R)
|
||||
Q <= 0;
|
||||
|
@ -283,7 +307,8 @@ module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D);
|
|||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D);
|
||||
//(* abc_box_id = 19, abc_flop *)
|
||||
module SB_DFFNESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
|
||||
always @(negedge C)
|
||||
if (E) begin
|
||||
if (S)
|
||||
|
@ -293,7 +318,8 @@ module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D);
|
|||
end
|
||||
endmodule
|
||||
|
||||
module SB_DFFNES (output `SB_DFF_REG, input C, E, S, D);
|
||||
//(* abc_box_id = 20, abc_flop *)
|
||||
module SB_DFFNES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
|
||||
always @(negedge C, posedge S)
|
||||
if (S)
|
||||
Q <= 1;
|
||||
|
@ -304,7 +330,7 @@ endmodule
|
|||
// SiliconBlue RAM Cells
|
||||
|
||||
module SB_RAM40_4K (
|
||||
output [15:0] RDATA,
|
||||
(* abc_flop_q *) output [15:0] RDATA,
|
||||
input RCLK, RCLKE, RE,
|
||||
input [10:0] RADDR,
|
||||
input WCLK, WCLKE, WE,
|
||||
|
@ -472,7 +498,7 @@ module SB_RAM40_4K (
|
|||
endmodule
|
||||
|
||||
module SB_RAM40_4KNR (
|
||||
output [15:0] RDATA,
|
||||
(* abc_flop_q *) output [15:0] RDATA,
|
||||
input RCLKN, RCLKE, RE,
|
||||
input [10:0] RADDR,
|
||||
input WCLK, WCLKE, WE,
|
||||
|
@ -537,7 +563,7 @@ module SB_RAM40_4KNR (
|
|||
endmodule
|
||||
|
||||
module SB_RAM40_4KNW (
|
||||
output [15:0] RDATA,
|
||||
(* abc_flop_q *) output [15:0] RDATA,
|
||||
input RCLK, RCLKE, RE,
|
||||
input [10:0] RADDR,
|
||||
input WCLKN, WCLKE, WE,
|
||||
|
@ -602,7 +628,7 @@ module SB_RAM40_4KNW (
|
|||
endmodule
|
||||
|
||||
module SB_RAM40_4KNRNW (
|
||||
output [15:0] RDATA,
|
||||
(* abc_flop_q *) output [15:0] RDATA,
|
||||
input RCLKN, RCLKE, RE,
|
||||
input [10:0] RADDR,
|
||||
input WCLKN, WCLKE, WE,
|
||||
|
@ -890,12 +916,13 @@ module SB_WARMBOOT (
|
|||
);
|
||||
endmodule
|
||||
|
||||
(* nomem2reg *)
|
||||
module SB_SPRAM256KA (
|
||||
input [13:0] ADDRESS,
|
||||
input [15:0] DATAIN,
|
||||
input [3:0] MASKWREN,
|
||||
input WREN, CHIPSELECT, CLOCK, STANDBY, SLEEP, POWEROFF,
|
||||
output reg [15:0] DATAOUT
|
||||
(* abc_flop_q *) output reg [15:0] DATAOUT
|
||||
);
|
||||
`ifndef BLACKBOX
|
||||
`ifndef EQUIV
|
||||
|
|
|
@ -37,6 +37,10 @@ struct SynthIce40Pass : public ScriptPass
|
|||
log("\n");
|
||||
log("This command runs synthesis for iCE40 FPGAs.\n");
|
||||
log("\n");
|
||||
log(" -device < hx | lp | u >\n");
|
||||
log(" optimise the synthesis netlist for the specified device.\n");
|
||||
log(" HX is the default target if no device argument specified.\n");
|
||||
log("\n");
|
||||
log(" -top <module>\n");
|
||||
log(" use the specified module as top module\n");
|
||||
log("\n");
|
||||
|
@ -102,7 +106,7 @@ struct SynthIce40Pass : public ScriptPass
|
|||
}
|
||||
|
||||
|
||||
string top_opt, blif_file, edif_file, json_file, abc;
|
||||
string top_opt, blif_file, edif_file, json_file, abc, device_opt;
|
||||
bool nocarry, nodffe, nobram, dsp, flatten, retime, relut, noabc, abc2, vpr;
|
||||
int min_ce_use;
|
||||
|
||||
|
@ -124,6 +128,7 @@ struct SynthIce40Pass : public ScriptPass
|
|||
abc2 = false;
|
||||
vpr = false;
|
||||
abc = "abc";
|
||||
device_opt = "hx";
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
|
@ -210,12 +215,18 @@ struct SynthIce40Pass : public ScriptPass
|
|||
abc = "abc9";
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-device" && argidx+1 < args.size()) {
|
||||
device_opt = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
if (device_opt != "hx" && device_opt != "lp" && device_opt !="u")
|
||||
log_cmd_error("Invalid or no device specified: '%s'\n", device_opt.c_str());
|
||||
|
||||
log_header(design, "Executing SYNTH_ICE40 pass.\n");
|
||||
log_push();
|
||||
|
@ -229,7 +240,7 @@ struct SynthIce40Pass : public ScriptPass
|
|||
{
|
||||
if (check_label("begin"))
|
||||
{
|
||||
run("read_verilog -lib +/ice40/cells_sim.v");
|
||||
run("read_verilog -lib -D ABC_MODEL +/ice40/cells_sim.v");
|
||||
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
|
||||
run("proc");
|
||||
}
|
||||
|
@ -282,7 +293,7 @@ struct SynthIce40Pass : public ScriptPass
|
|||
run("techmap");
|
||||
else
|
||||
run("techmap -map +/techmap.v -map +/ice40/arith_map.v");
|
||||
if (retime || help_mode)
|
||||
if ((retime || help_mode) && abc != "abc9")
|
||||
run(abc + " -dff", "(only if -retime)");
|
||||
run("ice40_opt");
|
||||
}
|
||||
|
@ -316,7 +327,10 @@ struct SynthIce40Pass : public ScriptPass
|
|||
run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)");
|
||||
}
|
||||
if (!noabc) {
|
||||
run(abc + " -dress -lut 4", "(skip if -noabc)");
|
||||
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("clean");
|
||||
if (relut || help_mode) {
|
||||
|
|
|
@ -38,7 +38,7 @@ struct SynthIntelPass : public ScriptPass {
|
|||
log("\n");
|
||||
log(" -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive>\n");
|
||||
log(" generate the synthesis netlist for the specified family.\n");
|
||||
log(" MAX10 is the default target if not family argument specified.\n");
|
||||
log(" MAX10 is the default target if no family argument specified.\n");
|
||||
log(" For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.\n");
|
||||
log(" Cyclone V and Arria 10 GX devices are experimental, use it with a10gx argument.\n");
|
||||
log("\n");
|
||||
|
@ -146,7 +146,7 @@ struct SynthIntelPass : public ScriptPass {
|
|||
if (!design->full_selection())
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
if (family_opt != "max10" && family_opt !="a10gx" && family_opt != "cyclonev" && family_opt !="cycloneiv" && family_opt !="cycloneive" && family_opt != "cyclone10")
|
||||
log_cmd_error("Invalid or not family specified: '%s'\n", family_opt.c_str());
|
||||
log_cmd_error("Invalid or no family specified: '%s'\n", family_opt.c_str());
|
||||
|
||||
log_header(design, "Executing SYNTH_INTEL pass.\n");
|
||||
log_push();
|
||||
|
|
|
@ -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; techmap; opt -full; abc9 -lut 4; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'"
|
||||
|
|
|
@ -9,8 +9,8 @@ opt
|
|||
stat
|
||||
# show -width
|
||||
select -assert-count 1 t:$sub
|
||||
select -assert-count 2 t:$mux
|
||||
select -assert-count 2 t:$shift
|
||||
select -assert-count 1 t:$mux
|
||||
select -assert-count 1 t:$shift
|
||||
select -assert-count 3 t:$shiftx
|
||||
|
||||
design -stash gate
|
||||
|
|
Loading…
Reference in New Issue