struct Ice40FfinitPass : public Pass {
Ice40FfinitPass() : Pass("ice40_ffinit", "iCE40: handle FF init values") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log("nonzero init values.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing ICE40_FFINIT pass (implement FF init values).\n");
SigMap sigmap(module);
pool<Wire*> init_wires;
dict<SigBit, State> initbits;
+ dict<SigBit, SigBit> initbit_to_wire;
pool<SigBit> handled_initbits;
for (auto wire : module->selected_wires())
{
- if (wire->attributes.count("\\init") == 0)
+ if (wire->attributes.count(ID::init) == 0)
continue;
SigSpec wirebits = sigmap(wire);
- Const initval = wire->attributes.at("\\init");
+ Const initval = wire->attributes.at(ID::init);
init_wires.insert(wire);
for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
continue;
if (initbits.count(bit)) {
- if (initbits.at(bit) != val)
- log_error("Conflicting init values for signal %s.\n", log_signal(bit));
+ if (initbits.at(bit) != val) {
+ log_warning("Conflicting init values for signal %s (%s = %s, %s = %s).\n",
+ log_signal(bit), log_signal(SigBit(wire, i)), log_signal(val),
+ log_signal(initbit_to_wire[bit]), log_signal(initbits.at(bit)));
+ initbits.at(bit) = State::Sx;
+ }
continue;
}
initbits[bit] = val;
+ initbit_to_wire[bit] = SigBit(wire, i);
}
}
pool<IdString> sb_dff_types = {
- "\\SB_DFF", "\\SB_DFFE", "\\SB_DFFSR", "\\SB_DFFR", "\\SB_DFFSS", "\\SB_DFFS", "\\SB_DFFESR",
- "\\SB_DFFER", "\\SB_DFFESS", "\\SB_DFFES", "\\SB_DFFN", "\\SB_DFFNE", "\\SB_DFFNSR", "\\SB_DFFNR",
- "\\SB_DFFNSS", "\\SB_DFFNS", "\\SB_DFFNESR", "\\SB_DFFNER", "\\SB_DFFNESS", "\\SB_DFFNES"
+ ID(SB_DFF), ID(SB_DFFE), ID(SB_DFFSR), ID(SB_DFFR), ID(SB_DFFSS), ID(SB_DFFS), ID(SB_DFFESR),
+ ID(SB_DFFER), ID(SB_DFFESS), ID(SB_DFFES), ID(SB_DFFN), ID(SB_DFFNE), ID(SB_DFFNSR), ID(SB_DFFNR),
+ ID(SB_DFFNSS), ID(SB_DFFNS), ID(SB_DFFNESR), ID(SB_DFFNER), ID(SB_DFFNESS), ID(SB_DFFNES)
};
for (auto cell : module->selected_cells())
if (!sb_dff_types.count(cell->type))
continue;
- SigBit sig_d = sigmap(cell->getPort("\\D"));
- SigBit sig_q = sigmap(cell->getPort("\\Q"));
+ SigSpec sig_d = cell->getPort(ID::D);
+ SigSpec sig_q = cell->getPort(ID::Q);
- if (!initbits.count(sig_q))
+ if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
continue;
- State val = initbits.at(sig_q);
- handled_initbits.insert(sig_q);
+ SigBit bit_d = sigmap(sig_d[0]);
+ SigBit bit_q = sigmap(sig_q[0]);
+
+ if (!initbits.count(bit_q))
+ continue;
+
+ State val = initbits.at(bit_q);
+
+ if (val == State::Sx)
+ continue;
+
+ handled_initbits.insert(bit_q);
log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type),
- log_signal(sig_q), val != State::S0 ? '1' : '0');
+ log_signal(bit_q), val != State::S0 ? '1' : '0');
if (val == State::S0)
continue;
if (type_str.back() == 'S') {
type_str.back() = 'R';
cell->type = type_str;
- cell->setPort("\\R", cell->getPort("\\S"));
- cell->unsetPort("\\S");
+ cell->setPort(ID::R, cell->getPort(ID::S));
+ cell->unsetPort(ID::S);
} else
if (type_str.back() == 'R') {
type_str.back() = 'S';
cell->type = type_str;
- cell->setPort("\\S", cell->getPort("\\R"));
- cell->unsetPort("\\R");
+ cell->setPort(ID::S, cell->getPort(ID::R));
+ cell->unsetPort(ID::R);
}
- Wire *new_sig_d = module->addWire(NEW_ID);
- Wire *new_sig_q = module->addWire(NEW_ID);
+ Wire *new_bit_d = module->addWire(NEW_ID);
+ Wire *new_bit_q = module->addWire(NEW_ID);
- module->addNotGate(NEW_ID, sig_d, new_sig_d);
- module->addNotGate(NEW_ID, new_sig_q, sig_q);
+ module->addNotGate(NEW_ID, bit_d, new_bit_d);
+ module->addNotGate(NEW_ID, new_bit_q, bit_q);
- cell->setPort("\\D", new_sig_d);
- cell->setPort("\\Q", new_sig_q);
+ cell->setPort(ID::D, new_bit_d);
+ cell->setPort(ID::Q, new_bit_q);
}
for (auto wire : init_wires)
{
- if (wire->attributes.count("\\init") == 0)
+ if (wire->attributes.count(ID::init) == 0)
continue;
SigSpec wirebits = sigmap(wire);
- Const &initval = wire->attributes.at("\\init");
+ Const &initval = wire->attributes.at(ID::init);
bool remove_attribute = true;
for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) {
}
if (remove_attribute)
- wire->attributes.erase("\\init");
+ wire->attributes.erase(ID::init);
}
}
}