mirror of https://github.com/YosysHQ/yosys.git
Merge pull request #1926 from YosysHQ/eddie/abc9_auto_dff
abc9: support seq synthesis when module has (* abc9_flop *) and bypass non-combinatorial (* abc9_box *)
This commit is contained in:
commit
2d573a0ff6
|
@ -76,9 +76,11 @@ void aiger_encode(std::ostream &f, int x)
|
|||
|
||||
struct XAigerWriter
|
||||
{
|
||||
Design *design;
|
||||
Module *module;
|
||||
SigMap sigmap;
|
||||
|
||||
dict<SigBit, State> init_map;
|
||||
pool<SigBit> input_bits, output_bits;
|
||||
dict<SigBit, SigBit> not_map, alias_map;
|
||||
dict<SigBit, pair<SigBit, SigBit>> and_map;
|
||||
|
@ -137,7 +139,7 @@ struct XAigerWriter
|
|||
return a;
|
||||
}
|
||||
|
||||
XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module)
|
||||
XAigerWriter(Module *module, bool dff_mode) : design(module->design), module(module), sigmap(module)
|
||||
{
|
||||
pool<SigBit> undriven_bits;
|
||||
pool<SigBit> unused_bits;
|
||||
|
@ -157,7 +159,8 @@ struct XAigerWriter
|
|||
if (wire->get_bool_attribute(ID::keep))
|
||||
sigmap.add(wire);
|
||||
|
||||
for (auto wire : module->wires())
|
||||
for (auto wire : module->wires()) {
|
||||
auto it = wire->attributes.find(ID::init);
|
||||
for (int i = 0; i < GetSize(wire); i++)
|
||||
{
|
||||
SigBit wirebit(wire, i);
|
||||
|
@ -174,17 +177,27 @@ struct XAigerWriter
|
|||
undriven_bits.insert(bit);
|
||||
unused_bits.insert(bit);
|
||||
|
||||
bool scc = wire->attributes.count(ID::abc9_scc);
|
||||
if (wire->port_input || scc)
|
||||
bool keep = wire->get_bool_attribute(ID::abc9_keep);
|
||||
if (wire->port_input || keep)
|
||||
input_bits.insert(bit);
|
||||
|
||||
bool keep = wire->get_bool_attribute(ID::keep);
|
||||
if (wire->port_output || keep || scc) {
|
||||
keep = keep || wire->get_bool_attribute(ID::keep);
|
||||
if (wire->port_output || keep) {
|
||||
if (bit != wirebit)
|
||||
alias_map[wirebit] = bit;
|
||||
output_bits.insert(wirebit);
|
||||
}
|
||||
|
||||
if (it != wire->attributes.end()) {
|
||||
auto s = it->second[i];
|
||||
if (s != State::Sx) {
|
||||
auto r = init_map.insert(std::make_pair(bit, it->second[i]));
|
||||
if (!r.second && r.first->second != it->second[i])
|
||||
log_error("Bit '%s' has a conflicting (* init *) value.\n", log_signal(bit));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TimingInfo timing;
|
||||
|
||||
|
@ -212,10 +225,7 @@ struct XAigerWriter
|
|||
continue;
|
||||
}
|
||||
|
||||
if (cell->type == ID($__ABC9_FF_) &&
|
||||
// The presence of an abc9_mergeability attribute indicates
|
||||
// that we do want to pass this flop to ABC
|
||||
cell->attributes.count(ID::abc9_mergeability))
|
||||
if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_)) && !cell->get_bool_attribute(ID::abc9_keep))
|
||||
{
|
||||
SigBit D = sigmap(cell->getPort(ID::D).as_bit());
|
||||
SigBit Q = sigmap(cell->getPort(ID::Q).as_bit());
|
||||
|
@ -231,31 +241,35 @@ struct XAigerWriter
|
|||
continue;
|
||||
}
|
||||
|
||||
RTLIL::Module* inst_module = module->design->module(cell->type);
|
||||
if (inst_module) {
|
||||
IdString derived_type = inst_module->derive(module->design, cell->parameters);
|
||||
inst_module = module->design->module(derived_type);
|
||||
log_assert(inst_module);
|
||||
|
||||
RTLIL::Module* inst_module = design->module(cell->type);
|
||||
if (inst_module && inst_module->get_blackbox_attribute()) {
|
||||
bool abc9_flop = false;
|
||||
if (!cell->has_keep_attr()) {
|
||||
auto it = cell->attributes.find(ID::abc9_box_seq);
|
||||
if (it != cell->attributes.end()) {
|
||||
int abc9_box_seq = it->second.as_int();
|
||||
if (GetSize(box_list) <= abc9_box_seq)
|
||||
box_list.resize(abc9_box_seq+1);
|
||||
box_list[abc9_box_seq] = cell;
|
||||
// Only flop boxes may have arrival times
|
||||
// (all others are combinatorial)
|
||||
abc9_flop = inst_module->get_bool_attribute(ID::abc9_flop);
|
||||
if (!abc9_flop)
|
||||
continue;
|
||||
}
|
||||
|
||||
auto it = cell->attributes.find(ID::abc9_box_seq);
|
||||
if (it != cell->attributes.end()) {
|
||||
log_assert(!cell->has_keep_attr());
|
||||
int abc9_box_seq = it->second.as_int();
|
||||
if (GetSize(box_list) <= abc9_box_seq)
|
||||
box_list.resize(abc9_box_seq+1);
|
||||
box_list[abc9_box_seq] = cell;
|
||||
// Only flop boxes may have arrival times
|
||||
// (all others are combinatorial)
|
||||
log_assert(cell->parameters.empty());
|
||||
abc9_flop = inst_module->get_bool_attribute(ID::abc9_flop);
|
||||
if (!abc9_flop)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!timing.count(derived_type))
|
||||
if (!cell->parameters.empty()) {
|
||||
auto derived_type = inst_module->derive(design, cell->parameters);
|
||||
inst_module = design->module(derived_type);
|
||||
log_assert(inst_module);
|
||||
log_assert(inst_module->get_blackbox_attribute());
|
||||
}
|
||||
|
||||
if (!timing.count(inst_module->name))
|
||||
timing.setup_module(inst_module);
|
||||
auto &t = timing.at(derived_type).arrival;
|
||||
auto &t = timing.at(inst_module->name).arrival;
|
||||
for (const auto &conn : cell->connections()) {
|
||||
auto port_wire = inst_module->wire(conn.first);
|
||||
if (!port_wire->port_output)
|
||||
|
@ -269,7 +283,7 @@ struct XAigerWriter
|
|||
#ifndef NDEBUG
|
||||
if (ys_debug(1)) {
|
||||
static std::set<std::tuple<IdString,IdString,int>> seen;
|
||||
if (seen.emplace(derived_type, conn.first, i).second) log("%s.%s[%d] abc9_arrival = %d\n",
|
||||
if (seen.emplace(inst_module->name, conn.first, i).second) log("%s.%s[%d] abc9_arrival = %d\n",
|
||||
log_id(cell->type), log_id(conn.first), i, d);
|
||||
}
|
||||
#endif
|
||||
|
@ -280,10 +294,6 @@ struct XAigerWriter
|
|||
if (abc9_flop)
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if (cell->type == ID($__ABC9_DELAY))
|
||||
log_error("Cell type '%s' not recognised. Check that '+/abc9_model.v' has been read.\n", cell->type.c_str());
|
||||
}
|
||||
|
||||
bool cell_known = inst_module || cell->known();
|
||||
for (const auto &c : cell->connections()) {
|
||||
|
@ -317,9 +327,9 @@ struct XAigerWriter
|
|||
for (auto cell : box_list) {
|
||||
log_assert(cell);
|
||||
|
||||
RTLIL::Module* box_module = module->design->module(cell->type);
|
||||
RTLIL::Module* box_module = design->module(cell->type);
|
||||
log_assert(box_module);
|
||||
log_assert(box_module->attributes.count(ID::abc9_box_id) || box_module->get_bool_attribute(ID::abc9_flop));
|
||||
log_assert(box_module->has_attribute(ID::abc9_box_id));
|
||||
|
||||
auto r = box_ports.insert(cell->type);
|
||||
if (r.second) {
|
||||
|
@ -383,27 +393,6 @@ struct XAigerWriter
|
|||
undriven_bits.erase(O);
|
||||
}
|
||||
}
|
||||
|
||||
// Connect <cell>.abc9_ff.Q (inserted by abc9_map.v) as the last input to the flop box
|
||||
if (box_module->get_bool_attribute(ID::abc9_flop)) {
|
||||
SigSpec rhs = module->wire(stringf("%s.abc9_ff.Q", cell->name.c_str()));
|
||||
if (rhs.empty())
|
||||
log_error("'%s.abc9_ff.Q' is not a wire present in module '%s'.\n", log_id(cell), log_id(module));
|
||||
|
||||
for (auto b : rhs) {
|
||||
SigBit I = sigmap(b);
|
||||
if (b == RTLIL::Sx)
|
||||
b = State::S0;
|
||||
else if (I != b) {
|
||||
if (I == RTLIL::Sx)
|
||||
alias_map[b] = State::S0;
|
||||
else
|
||||
alias_map[b] = I;
|
||||
}
|
||||
co_bits.emplace_back(b);
|
||||
unused_bits.erase(I);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto bit : input_bits)
|
||||
|
@ -419,16 +408,14 @@ struct XAigerWriter
|
|||
undriven_bits.erase(bit);
|
||||
}
|
||||
|
||||
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 ||
|
||||
(a.wire->port_id == b.wire->port_id && a.offset < b.offset);
|
||||
}
|
||||
};
|
||||
input_bits.sort(sort_by_port_id());
|
||||
output_bits.sort(sort_by_port_id());
|
||||
}
|
||||
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 ||
|
||||
(a.wire->port_id == b.wire->port_id && a.offset < b.offset);
|
||||
}
|
||||
};
|
||||
input_bits.sort(sort_by_port_id());
|
||||
output_bits.sort(sort_by_port_id());
|
||||
|
||||
aig_map[State::S0] = 0;
|
||||
aig_map[State::S1] = 1;
|
||||
|
@ -589,17 +576,14 @@ struct XAigerWriter
|
|||
int box_count = 0;
|
||||
for (auto cell : box_list) {
|
||||
log_assert(cell);
|
||||
log_assert(cell->parameters.empty());
|
||||
|
||||
RTLIL::Module* box_module = module->design->module(cell->type);
|
||||
log_assert(box_module);
|
||||
|
||||
IdString derived_type = box_module->derive(box_module->design, cell->parameters);
|
||||
box_module = box_module->design->module(derived_type);
|
||||
log_assert(box_module);
|
||||
|
||||
auto r = cell_cache.insert(derived_type);
|
||||
auto r = cell_cache.insert(cell->type);
|
||||
auto &v = r.first->second;
|
||||
if (r.second) {
|
||||
RTLIL::Module* box_module = design->module(cell->type);
|
||||
log_assert(box_module);
|
||||
|
||||
int box_inputs = 0, box_outputs = 0;
|
||||
for (auto port_name : box_module->ports) {
|
||||
RTLIL::Wire *w = box_module->wire(port_name);
|
||||
|
@ -610,11 +594,6 @@ struct XAigerWriter
|
|||
box_outputs += GetSize(w);
|
||||
}
|
||||
|
||||
// For flops only, create an extra 1-bit input that drives a new wire
|
||||
// called "<cell>.abc9_ff.Q" that is used below
|
||||
if (box_module->get_bool_attribute(ID::abc9_flop))
|
||||
box_inputs++;
|
||||
|
||||
std::get<0>(v) = box_inputs;
|
||||
std::get<1>(v) = box_outputs;
|
||||
std::get<2>(v) = box_module->attributes.at(ID::abc9_box_id).as_int();
|
||||
|
@ -635,23 +614,27 @@ struct XAigerWriter
|
|||
auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1);
|
||||
write_s_buffer(ff_bits.size());
|
||||
|
||||
dict<SigSpec, int> clk_to_mergeability;
|
||||
for (const auto &i : ff_bits) {
|
||||
const SigBit &d = i.first;
|
||||
const Cell *cell = i.second;
|
||||
|
||||
int mergeability = cell->attributes.at(ID::abc9_mergeability).as_int();
|
||||
SigSpec clk_and_pol{sigmap(cell->getPort(ID::C)), cell->type[6] == 'P' ? State::S1 : State::S0};
|
||||
auto r = clk_to_mergeability.insert(std::make_pair(clk_and_pol, clk_to_mergeability.size()+1));
|
||||
int mergeability = r.first->second;
|
||||
log_assert(mergeability > 0);
|
||||
write_r_buffer(mergeability);
|
||||
|
||||
Const init = cell->attributes.at(ID::abc9_init, State::Sx);
|
||||
log_assert(GetSize(init) == 1);
|
||||
SigBit Q = sigmap(cell->getPort(ID::Q));
|
||||
State init = init_map.at(Q, State::Sx);
|
||||
log_debug("Cell '%s' (type %s) has (* init *) value '%s'.\n", log_id(cell), log_id(cell->type), log_signal(init));
|
||||
if (init == State::S1)
|
||||
write_s_buffer(1);
|
||||
else if (init == State::S0)
|
||||
write_s_buffer(0);
|
||||
else {
|
||||
log_assert(init == State::Sx);
|
||||
write_s_buffer(0);
|
||||
write_s_buffer(2);
|
||||
}
|
||||
|
||||
// Use arrival time from output of flop box
|
||||
|
@ -671,10 +654,16 @@ struct XAigerWriter
|
|||
f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
|
||||
f.write(buffer_str.data(), buffer_str.size());
|
||||
|
||||
RTLIL::Module *holes_module = module->design->module(stringf("%s$holes", module->name.c_str()));
|
||||
RTLIL::Design *holes_design;
|
||||
auto it = saved_designs.find("$abc9_holes");
|
||||
if (it != saved_designs.end())
|
||||
holes_design = it->second;
|
||||
else
|
||||
holes_design = nullptr;
|
||||
RTLIL::Module *holes_module = holes_design ? holes_design->module(module->name) : nullptr;
|
||||
if (holes_module) {
|
||||
std::stringstream a_buffer;
|
||||
XAigerWriter writer(holes_module, true /* holes_mode */);
|
||||
XAigerWriter writer(holes_module, false /* dff_mode */);
|
||||
writer.write_aiger(a_buffer, false /*ascii_mode*/);
|
||||
|
||||
f << "a";
|
||||
|
@ -704,10 +693,10 @@ struct XAigerWriter
|
|||
|
||||
f << stringf("Generated by %s\n", yosys_version_str);
|
||||
|
||||
module->design->scratchpad_set_int("write_xaiger.num_ands", and_map.size());
|
||||
module->design->scratchpad_set_int("write_xaiger.num_wires", aig_map.size());
|
||||
module->design->scratchpad_set_int("write_xaiger.num_inputs", input_bits.size());
|
||||
module->design->scratchpad_set_int("write_xaiger.num_outputs", output_bits.size());
|
||||
design->scratchpad_set_int("write_xaiger.num_ands", and_map.size());
|
||||
design->scratchpad_set_int("write_xaiger.num_wires", aig_map.size());
|
||||
design->scratchpad_set_int("write_xaiger.num_inputs", input_bits.size());
|
||||
design->scratchpad_set_int("write_xaiger.num_outputs", output_bits.size());
|
||||
}
|
||||
|
||||
void write_map(std::ostream &f)
|
||||
|
@ -761,10 +750,10 @@ struct XAigerBackend : public Backend {
|
|||
log(" write_xaiger [options] [filename]\n");
|
||||
log("\n");
|
||||
log("Write the top module (according to the (* top *) attribute or if only one module\n");
|
||||
log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, $_ABC9_FF_, or");
|
||||
log("non (* abc9_box_id *) cells will be converted into psuedo-inputs and\n");
|
||||
log("pseudo-outputs. Whitebox contents will be taken from the '<module-name>$holes'\n");
|
||||
log("module, if it exists.\n");
|
||||
log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, (optionally\n");
|
||||
log("$_DFF_N_, $_DFF_P_), or non (* abc9_box *) cells will be converted into psuedo-\n");
|
||||
log("inputs and pseudo-outputs. Whitebox contents will be taken from the equivalent\n");
|
||||
log("module in the '$abc9_holes' design, if it exists.\n");
|
||||
log("\n");
|
||||
log(" -ascii\n");
|
||||
log(" write ASCII version of AIGER format\n");
|
||||
|
@ -772,10 +761,13 @@ struct XAigerBackend : public Backend {
|
|||
log(" -map <filename>\n");
|
||||
log(" write an extra file with port and box symbols\n");
|
||||
log("\n");
|
||||
log(" -dff\n");
|
||||
log(" write $_DFF_[NP]_ cells\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
bool ascii_mode = false;
|
||||
bool ascii_mode = false, dff_mode = false;
|
||||
std::string map_filename;
|
||||
|
||||
log_header(design, "Executing XAIGER backend.\n");
|
||||
|
@ -791,6 +783,10 @@ struct XAigerBackend : public Backend {
|
|||
map_filename = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-dff") {
|
||||
dff_mode = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(f, filename, args, argidx, !ascii_mode);
|
||||
|
@ -808,7 +804,7 @@ struct XAigerBackend : public Backend {
|
|||
if (!top_module->memories.empty())
|
||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", log_id(top_module));
|
||||
|
||||
XAigerWriter writer(top_module);
|
||||
XAigerWriter writer(top_module, dff_mode);
|
||||
writer.write_aiger(*f, ascii_mode);
|
||||
|
||||
if (!map_filename.empty()) {
|
||||
|
|
|
@ -454,6 +454,14 @@ void AigerReader::parse_xaiger()
|
|||
for (unsigned i = 0; i < flopNum; i++)
|
||||
mergeability.emplace_back(parse_xaiger_literal(f));
|
||||
}
|
||||
else if (c == 's') {
|
||||
uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
|
||||
flopNum = parse_xaiger_literal(f);
|
||||
log_assert(dataSize == (flopNum+1) * sizeof(uint32_t));
|
||||
initial_state.reserve(flopNum);
|
||||
for (unsigned i = 0; i < flopNum; i++)
|
||||
initial_state.emplace_back(parse_xaiger_literal(f));
|
||||
}
|
||||
else if (c == 'n') {
|
||||
parse_xaiger_literal(f);
|
||||
f >> s;
|
||||
|
@ -767,6 +775,7 @@ void AigerReader::post_process()
|
|||
}
|
||||
}
|
||||
|
||||
dict<int, Wire*> mergeability_to_clock;
|
||||
for (uint32_t i = 0; i < flopNum; i++) {
|
||||
RTLIL::Wire *d = outputs[outputs.size() - flopNum + i];
|
||||
log_assert(d);
|
||||
|
@ -778,10 +787,9 @@ void AigerReader::post_process()
|
|||
log_assert(q->port_input);
|
||||
q->port_input = false;
|
||||
|
||||
auto ff = module->addCell(NEW_ID, ID($__ABC9_FF_));
|
||||
ff->setPort(ID::D, d);
|
||||
ff->setPort(ID::Q, q);
|
||||
Cell* ff = module->addFfGate(NEW_ID, d, q);
|
||||
ff->attributes[ID::abc9_mergeability] = mergeability[i];
|
||||
q->attributes[ID::init] = initial_state[i];
|
||||
}
|
||||
|
||||
dict<RTLIL::IdString, std::pair<int,int>> wideports_cache;
|
||||
|
|
|
@ -45,7 +45,7 @@ struct AigerReader
|
|||
std::vector<RTLIL::Wire*> outputs;
|
||||
std::vector<RTLIL::Wire*> bad_properties;
|
||||
std::vector<RTLIL::Cell*> boxes;
|
||||
std::vector<int> mergeability;
|
||||
std::vector<int> mergeability, initial_state;
|
||||
|
||||
AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports);
|
||||
void parse_aiger();
|
||||
|
|
|
@ -2,13 +2,12 @@ X(A)
|
|||
X(abc9_box)
|
||||
X(abc9_box_id)
|
||||
X(abc9_box_seq)
|
||||
X(abc9_bypass)
|
||||
X(abc9_carry)
|
||||
X(abc9_flop)
|
||||
X(abc9_holes)
|
||||
X(abc9_init)
|
||||
X(abc9_keep)
|
||||
X(abc9_lut)
|
||||
X(abc9_mergeability)
|
||||
X(abc9_scc)
|
||||
X(abc9_scc_id)
|
||||
X(abcgroup)
|
||||
X(ABITS)
|
||||
|
|
|
@ -82,6 +82,9 @@ struct TimingInfo
|
|||
|
||||
for (auto cell : module->cells()) {
|
||||
if (cell->type == ID($specify2)) {
|
||||
auto en = cell->getPort(ID::EN);
|
||||
if (en.is_fully_const() && !en.as_bool())
|
||||
continue;
|
||||
auto src = cell->getPort(ID::SRC);
|
||||
auto dst = cell->getPort(ID::DST);
|
||||
for (const auto &c : src.chunks())
|
||||
|
@ -128,11 +131,9 @@ struct TimingInfo
|
|||
int rise_max = cell->getParam(ID::T_RISE_MAX).as_int();
|
||||
int fall_max = cell->getParam(ID::T_FALL_MAX).as_int();
|
||||
int max = std::max(rise_max,fall_max);
|
||||
if (max < 0)
|
||||
log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell));
|
||||
if (max <= 0) {
|
||||
log_debug("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell));
|
||||
continue;
|
||||
if (max < 0) {
|
||||
log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell));
|
||||
max = 0;
|
||||
}
|
||||
for (const auto &d : dst) {
|
||||
auto &v = t.arrival[NameBit(d)];
|
||||
|
@ -152,11 +153,9 @@ struct TimingInfo
|
|||
if (!c.wire->port_input)
|
||||
log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst));
|
||||
int max = cell->getParam(ID::T_LIMIT_MAX).as_int();
|
||||
if (max < 0)
|
||||
log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell));
|
||||
if (max <= 0) {
|
||||
log_debug("Module '%s' contains specify cell '%s' with T_LIMIT_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell));
|
||||
continue;
|
||||
if (max < 0) {
|
||||
log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell));
|
||||
max = 0;
|
||||
}
|
||||
for (const auto &s : src) {
|
||||
auto &v = t.required[NameBit(s)];
|
||||
|
|
|
@ -151,8 +151,8 @@ struct Abc9Pass : public ScriptPass
|
|||
log(" specified).\n");
|
||||
log("\n");
|
||||
log(" -dff\n");
|
||||
log(" also pass $_ABC9_FF_ cells through to ABC. modules with many clock\n");
|
||||
log(" domains are marked as such and automatically partitioned by ABC.\n");
|
||||
log(" also pass $_DFF_[NP]_ cells through to ABC. modules with many clock\n");
|
||||
log(" domains are supported and automatically partitioned by ABC.\n");
|
||||
log("\n");
|
||||
log(" -nocleanup\n");
|
||||
log(" when this option is used, the temporary files created by this pass\n");
|
||||
|
@ -274,40 +274,106 @@ struct Abc9Pass : public ScriptPass
|
|||
|
||||
void script() YS_OVERRIDE
|
||||
{
|
||||
if (check_label("check")) {
|
||||
if (help_mode)
|
||||
run("abc9_ops -check [-dff]", "(option if -dff)");
|
||||
else
|
||||
run(stringf("abc9_ops -check %s", dff_mode ? "-dff" : ""));
|
||||
}
|
||||
|
||||
if (check_label("map")) {
|
||||
if (help_mode)
|
||||
run("abc9_ops -prep_hier -prep_bypass [-prep_dff -dff]", "(option if -dff)");
|
||||
else
|
||||
run(stringf("abc9_ops -prep_hier -prep_bypass %s", dff_mode ? "-prep_dff -dff" : ""));
|
||||
if (dff_mode) {
|
||||
run("design -copy-to $abc9_map @$abc9_flops", "(only if -dff)");
|
||||
run("select -unset $abc9_flops", " (only if -dff)");
|
||||
}
|
||||
run("design -stash $abc9");
|
||||
run("design -load $abc9_map");
|
||||
run("proc");
|
||||
run("wbflip");
|
||||
run("techmap");
|
||||
run("opt");
|
||||
if (dff_mode || help_mode) {
|
||||
if (!help_mode)
|
||||
active_design->scratchpad_unset("abc9_ops.prep_dff_submod.did_something");
|
||||
run("abc9_ops -prep_dff_submod", " (only if -dff)"); // rewrite specify
|
||||
bool did_something = help_mode || active_design->scratchpad_get_bool("abc9_ops.prep_dff_submod.did_something");
|
||||
if (did_something) {
|
||||
// select all $_DFF_[NP]_
|
||||
// then select all its fanins
|
||||
// then select all fanouts of all that
|
||||
// lastly remove $_DFF_[NP]_ cells
|
||||
run("setattr -set submod \"$abc9_flop\" t:$_DFF_?_ %ci* %co* t:$_DFF_?_ %d", " (only if -dff)");
|
||||
run("submod", " (only if -dff)");
|
||||
run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop", "(only if -dff)");
|
||||
if (help_mode) {
|
||||
run("foreach module in design");
|
||||
run(" rename <module-name>_$abc9_flop _TECHMAP_REPLACE_", " (only if -dff)");
|
||||
}
|
||||
else {
|
||||
// Rename all submod-s to _TECHMAP_REPLACE_ to inherit name + attrs
|
||||
for (auto module : active_design->selected_modules()) {
|
||||
active_design->selected_active_module = module->name.str();
|
||||
if (module->cell(stringf("%s_$abc9_flop", module->name.c_str())))
|
||||
run(stringf("rename %s_$abc9_flop _TECHMAP_REPLACE_", module->name.c_str()));
|
||||
}
|
||||
active_design->selected_active_module.clear();
|
||||
}
|
||||
run("abc9_ops -prep_dff_unmap", " (only if -dff)");
|
||||
run("design -copy-to $abc9 =*_$abc9_flop", " (only if -dff)"); // copy submod out
|
||||
run("delete =*_$abc9_flop", " (only if -dff)");
|
||||
}
|
||||
}
|
||||
run("design -stash $abc9_map");
|
||||
run("design -load $abc9");
|
||||
run("design -delete $abc9");
|
||||
if (help_mode)
|
||||
run("techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v [-D DFF]", "(option if -dff)");
|
||||
else
|
||||
run(stringf("techmap -wb -max_iter 1 -map %%$abc9_map -map +/abc9_map.v %s", dff_mode ? "-D DFF" : ""));
|
||||
run("design -delete $abc9_map");
|
||||
}
|
||||
|
||||
if (check_label("pre")) {
|
||||
run("abc9_ops -check");
|
||||
run("read_verilog -icells -lib -specify +/abc9_model.v");
|
||||
run("scc -set_attr abc9_scc_id {}");
|
||||
if (help_mode)
|
||||
run("abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)");
|
||||
else
|
||||
run("abc9_ops -mark_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)");
|
||||
run("abc9_ops -mark_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : ""));
|
||||
if (help_mode)
|
||||
run("abc9_ops -prep_lut <maxlut>", "(skip if -lut or -luts)");
|
||||
else if (!lut_mode)
|
||||
run(stringf("abc9_ops -prep_lut %d", maxlut));
|
||||
if (help_mode)
|
||||
run("abc9_ops -prep_box [-dff]", "(skip if -box)");
|
||||
run("abc9_ops -prep_box", "(skip if -box)");
|
||||
else if (box_file.empty())
|
||||
run(stringf("abc9_ops -prep_box %s", dff_mode ? "-dff" : ""));
|
||||
run("select -set abc9_holes A:abc9_holes");
|
||||
run("flatten -wb @abc9_holes");
|
||||
run("techmap @abc9_holes");
|
||||
if (dff_mode || help_mode)
|
||||
run("abc9_ops -prep_dff", "(only if -dff)");
|
||||
run("opt -purge @abc9_holes");
|
||||
run("aigmap");
|
||||
run("wbflip @abc9_holes");
|
||||
run("abc9_ops -prep_box");
|
||||
if (saved_designs.count("$abc9_holes") || help_mode) {
|
||||
run("design -stash $abc9");
|
||||
run("design -load $abc9_holes");
|
||||
run("techmap -wb -map %$abc9 -map +/techmap.v");
|
||||
run("opt -purge");
|
||||
run("aigmap");
|
||||
run("design -stash $abc9_holes");
|
||||
run("design -load $abc9");
|
||||
run("design -delete $abc9");
|
||||
}
|
||||
}
|
||||
|
||||
if (check_label("map")) {
|
||||
if (check_label("exe")) {
|
||||
run("aigmap");
|
||||
if (help_mode) {
|
||||
run("foreach module in selection");
|
||||
run(" abc9_ops -write_lut <abc-temp-dir>/input.lut", "(skip if '-lut' or '-luts')");
|
||||
run(" abc9_ops -write_box <abc-temp-dir>/input.box");
|
||||
run(" write_xaiger -map <abc-temp-dir>/input.sym <abc-temp-dir>/input.xaig");
|
||||
run(" abc9_exe [options] -cwd <abc-temp-dir> [-lut <abc-temp-dir>/input.lut] -box <abc-temp-dir>/input.box");
|
||||
run(" abc9_ops -write_box <abc-temp-dir>/input.box", "(skip if '-box')");
|
||||
run(" write_xaiger -map <abc-temp-dir>/input.sym [-dff] <abc-temp-dir>/input.xaig");
|
||||
run(" abc9_exe [options] -cwd <abc-temp-dir> -lut [<abc-temp-dir>/input.lut] -box [<abc-temp-dir>/input.box]");
|
||||
run(" read_aiger -xaiger -wideports -module_name <module-name>$abc9 -map <abc-temp-dir>/input.sym <abc-temp-dir>/output.aig");
|
||||
run(" abc9_ops -reintegrate");
|
||||
run(" abc9_ops -reintegrate [-dff]");
|
||||
}
|
||||
else {
|
||||
auto selected_modules = active_design->selected_modules();
|
||||
|
@ -318,7 +384,6 @@ struct Abc9Pass : public ScriptPass
|
|||
log("Skipping module %s as it contains processes.\n", log_id(mod));
|
||||
continue;
|
||||
}
|
||||
log_assert(!mod->attributes.count(ID::abc9_box_id));
|
||||
|
||||
log_push();
|
||||
active_design->selection().select(mod);
|
||||
|
@ -333,8 +398,9 @@ struct Abc9Pass : public ScriptPass
|
|||
|
||||
if (!lut_mode)
|
||||
run_nocheck(stringf("abc9_ops -write_lut %s/input.lut", tempdir_name.c_str()));
|
||||
run_nocheck(stringf("abc9_ops -write_box %s/input.box", tempdir_name.c_str()));
|
||||
run_nocheck(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()));
|
||||
if (box_file.empty())
|
||||
run_nocheck(stringf("abc9_ops -write_box %s/input.box", tempdir_name.c_str()));
|
||||
run_nocheck(stringf("write_xaiger -map %s/input.sym %s %s/input.xaig", tempdir_name.c_str(), dff_mode ? "-dff" : "", tempdir_name.c_str()));
|
||||
|
||||
int num_outputs = active_design->scratchpad_get_int("write_xaiger.num_outputs");
|
||||
|
||||
|
@ -349,10 +415,13 @@ struct Abc9Pass : public ScriptPass
|
|||
abc9_exe_cmd += stringf("%s -cwd %s", exe_cmd.str().c_str(), tempdir_name.c_str());
|
||||
if (!lut_mode)
|
||||
abc9_exe_cmd += stringf(" -lut %s/input.lut", tempdir_name.c_str());
|
||||
abc9_exe_cmd += stringf(" -box %s/input.box", tempdir_name.c_str());
|
||||
if (box_file.empty())
|
||||
abc9_exe_cmd += stringf(" -box %s/input.box", tempdir_name.c_str());
|
||||
else
|
||||
abc9_exe_cmd += stringf(" -box %s", box_file.c_str());
|
||||
run_nocheck(abc9_exe_cmd);
|
||||
run_nocheck(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod), tempdir_name.c_str(), tempdir_name.c_str()));
|
||||
run_nocheck("abc9_ops -reintegrate");
|
||||
run_nocheck(stringf("abc9_ops -reintegrate %s", dff_mode ? "-dff" : ""));
|
||||
}
|
||||
else
|
||||
log("Don't call ABC as there is nothing to map.\n");
|
||||
|
@ -369,6 +438,14 @@ struct Abc9Pass : public ScriptPass
|
|||
active_design->selection_stack.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
if (check_label("unmap")) {
|
||||
run("techmap -wb -map %$abc9_unmap -map +/abc9_unmap.v"); // techmap user design from submod back to original cell
|
||||
// ($_DFF_[NP]_ already shorted by -reintegrate)
|
||||
run("design -delete $abc9_unmap");
|
||||
if (saved_designs.count("$abc9_holes") || help_mode)
|
||||
run("design -delete $abc9_holes");
|
||||
}
|
||||
}
|
||||
} Abc9Pass;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,4 +30,6 @@ $(eval $(call add_share_file,share,techlibs/common/cmp2lut.v))
|
|||
$(eval $(call add_share_file,share,techlibs/common/cells.lib))
|
||||
$(eval $(call add_share_file,share,techlibs/common/mul2dsp.v))
|
||||
$(eval $(call add_share_file,share,techlibs/common/abc9_model.v))
|
||||
$(eval $(call add_share_file,share,techlibs/common/abc9_map.v))
|
||||
$(eval $(call add_share_file,share,techlibs/common/abc9_unmap.v))
|
||||
$(eval $(call add_share_file,share,techlibs/common/cmp2lcu.v))
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
`ifdef DFF
|
||||
(* techmap_celltype = "$_DFF_N_ $_DFF_P_" *)
|
||||
module $_DFF_x_(input C, D, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
parameter _TECHMAP_CELLTYPE_ = "";
|
||||
wire D_;
|
||||
generate if (_TECHMAP_CELLTYPE_ == "$_DFF_N_") begin
|
||||
if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin
|
||||
$__DFF_N__$abc9_flop _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_));
|
||||
$_DFF_N_ ff (.C(C), .D(D_), .Q(Q));
|
||||
end
|
||||
else
|
||||
(* abc9_keep *) $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q));
|
||||
end
|
||||
else if (_TECHMAP_CELLTYPE_ == "$_DFF_P_") begin
|
||||
if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin
|
||||
$__DFF_P__$abc9_flop _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_));
|
||||
$_DFF_P_ ff (.C(C), .D(D_), .Q(Q));
|
||||
end
|
||||
else
|
||||
(* abc9_keep *) $_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q));
|
||||
end
|
||||
else if (_TECHMAP_CELLTYPE_ != "")
|
||||
$error("Unrecognised _TECHMAP_CELLTYPE_");
|
||||
endgenerate
|
||||
endmodule
|
||||
`endif
|
|
@ -1,10 +1,25 @@
|
|||
module \$__ABC9_FF_ (input D, output Q);
|
||||
endmodule
|
||||
|
||||
(* abc9_box *)
|
||||
module \$__ABC9_DELAY (input I, output O);
|
||||
module $__ABC9_DELAY (input I, output O);
|
||||
parameter DELAY = 0;
|
||||
specify
|
||||
(I => O) = DELAY;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, abc9_box, lib_whitebox *)
|
||||
module $__DFF_N__$abc9_flop (input C, D, Q, output n1);
|
||||
assign n1 = D;
|
||||
specify
|
||||
$setup(D, posedge C, 0);
|
||||
(posedge C => (n1:D)) = 0;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, abc9_box, lib_whitebox *)
|
||||
module $__DFF_P__$abc9_flop (input C, D, Q, output n1);
|
||||
assign n1 = D;
|
||||
specify
|
||||
$setup(D, posedge C, 0);
|
||||
(posedge C => (n1:D)) = 0;
|
||||
endspecify
|
||||
endmodule
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
(* techmap_celltype = "$__DFF_N__$abc9_flop $__DFF_P__$abc9_flop" *)
|
||||
module $__DFF_x__$abc9_flop (input C, D, Q, output n1);
|
||||
parameter _TECHMAP_CELLTYPE_ = "";
|
||||
generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N__$abc9_flop")
|
||||
$_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q));
|
||||
else if (_TECHMAP_CELLTYPE_ == "$__DFF_P__$abc9_flop")
|
||||
$_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q));
|
||||
else if (_TECHMAP_CELLTYPE_ != "")
|
||||
$error("Unrecognised _TECHMAP_CELLTYPE_");
|
||||
endgenerate
|
||||
endmodule
|
|
@ -23,9 +23,6 @@ $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams.txt))
|
|||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_map.v))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dsp_map.v))
|
||||
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_map.v))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_unmap.v))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_model.v))
|
||||
|
||||
EXTRA_OBJS += techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
// ---------------------------------------
|
||||
|
||||
// Attach a (combinatorial) black-box onto the output
|
||||
// of this LUTRAM primitive to capture its
|
||||
// asynchronous read behaviour
|
||||
module TRELLIS_DPR16X4 (
|
||||
(* techmap_autopurge *) input [3:0] DI,
|
||||
(* techmap_autopurge *) input [3:0] WAD,
|
||||
(* techmap_autopurge *) input WRE,
|
||||
(* techmap_autopurge *) input WCK,
|
||||
(* techmap_autopurge *) input [3:0] RAD,
|
||||
output [3:0] DO
|
||||
);
|
||||
parameter WCKMUX = "WCK";
|
||||
parameter WREMUX = "WRE";
|
||||
parameter [63:0] INITVAL = 64'h0000000000000000;
|
||||
wire [3:0] $DO;
|
||||
|
||||
TRELLIS_DPR16X4 #(
|
||||
.WCKMUX(WCKMUX), .WREMUX(WREMUX), .INITVAL(INITVAL)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.DI(DI), .WAD(WAD), .WRE(WRE), .WCK(WCK),
|
||||
.RAD(RAD), .DO($DO)
|
||||
);
|
||||
|
||||
$__ABC9_DPR16X4_COMB do (.$DO($DO), .RAD(RAD), .DO(DO));
|
||||
endmodule
|
|
@ -1,5 +0,0 @@
|
|||
// ---------------------------------------
|
||||
|
||||
module \$__ABC9_DPR16X4_COMB (input [3:0] $DO, RAD, output [3:0] DO);
|
||||
assign DO = $DO;
|
||||
endmodule
|
|
@ -186,6 +186,7 @@ module PFUMX (input ALUT, BLUT, C0, output Z);
|
|||
endmodule
|
||||
|
||||
// ---------------------------------------
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module TRELLIS_DPR16X4 (
|
||||
input [3:0] DI,
|
||||
input [3:0] WAD,
|
||||
|
@ -222,10 +223,16 @@ module TRELLIS_DPR16X4 (
|
|||
mem[WAD] <= DI;
|
||||
|
||||
assign DO = mem[RAD];
|
||||
|
||||
specify
|
||||
// TODO
|
||||
(RAD *> DO) = 0;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
// ---------------------------------------
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module DPR16X4C (
|
||||
input [3:0] DI,
|
||||
input WCK, WRE,
|
||||
|
@ -281,6 +288,10 @@ module DPR16X4C (
|
|||
|
||||
assign DO = ram[RAD];
|
||||
|
||||
specify
|
||||
// TODO
|
||||
(RAD *> DO) = 0;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
// ---------------------------------------
|
||||
|
@ -294,6 +305,9 @@ endmodule
|
|||
|
||||
// ---------------------------------------
|
||||
|
||||
`ifdef YOSYS
|
||||
(* abc9_flop=(SRMODE != "ASYNC"), abc9_box=(SRMODE == "ASYNC"), lib_whitebox *)
|
||||
`endif
|
||||
module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q);
|
||||
parameter GSR = "ENABLED";
|
||||
parameter [127:0] CEMUX = "1";
|
||||
|
@ -340,6 +354,38 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q);
|
|||
Q <= DI;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate
|
||||
// TODO
|
||||
if (CLKMUX == "INV")
|
||||
specify
|
||||
$setup(DI, negedge CLK, 0);
|
||||
$setup(CE, negedge CLK, 0);
|
||||
$setup(LSR, negedge CLK, 0);
|
||||
`ifndef YOSYS
|
||||
if (SRMODE == "ASYNC" && muxlsr) (negedge CLK => (Q : srval)) = 0;
|
||||
`else
|
||||
if (SRMODE == "ASYNC" && muxlsr) (LSR => Q) = 0; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
if (!muxlsr && muxce) (negedge CLK => (Q : DI)) = 0;
|
||||
endspecify
|
||||
else
|
||||
specify
|
||||
$setup(DI, posedge CLK, 0);
|
||||
$setup(CE, posedge CLK, 0);
|
||||
$setup(LSR, posedge CLK, 0);
|
||||
`ifndef YOSYS
|
||||
if (SRMODE == "ASYNC" && muxlsr) (posedge CLK => (Q : srval)) = 0;
|
||||
`else
|
||||
if (SRMODE == "ASYNC" && muxlsr) (LSR => Q) = 0; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
if (!muxlsr && muxce) (posedge CLK => (Q : DI)) = 0;
|
||||
endspecify
|
||||
endgenerate
|
||||
endmodule
|
||||
|
||||
// ---------------------------------------
|
||||
|
|
|
@ -66,6 +66,9 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
log(" -noflatten\n");
|
||||
log(" do not flatten design before synthesis\n");
|
||||
log("\n");
|
||||
log(" -dff\n");
|
||||
log(" run 'abc'/'abc9' with -dff option\n");
|
||||
log("\n");
|
||||
log(" -retime\n");
|
||||
log(" run 'abc' with '-dff -D 1' options\n");
|
||||
log("\n");
|
||||
|
@ -107,7 +110,7 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
}
|
||||
|
||||
string top_opt, blif_file, edif_file, json_file;
|
||||
bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, retime, abc2, abc9, nodsp, vpr;
|
||||
bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, dff, retime, abc2, abc9, nodsp, vpr;
|
||||
|
||||
void clear_flags() YS_OVERRIDE
|
||||
{
|
||||
|
@ -122,6 +125,7 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
nowidelut = false;
|
||||
asyncprld = false;
|
||||
flatten = true;
|
||||
dff = false;
|
||||
retime = false;
|
||||
abc2 = false;
|
||||
vpr = false;
|
||||
|
@ -169,6 +173,10 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
flatten = false;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-dff") {
|
||||
dff = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-retime") {
|
||||
retime = true;
|
||||
continue;
|
||||
|
@ -307,6 +315,8 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
run("opt_clean");
|
||||
if (!nodffe)
|
||||
run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*");
|
||||
if ((abc9 && dff) || help_mode)
|
||||
run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "(only if -abc9 and -dff");
|
||||
run(stringf("techmap -D NO_LUT %s -map +/ecp5/cells_map.v", help_mode ? "[-D ASYNC_PRLD]" : (asyncprld ? "-D ASYNC_PRLD" : "")));
|
||||
run("opt_expr -undriven -mux_undef");
|
||||
run("simplemap");
|
||||
|
@ -318,17 +328,13 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
|
||||
if (check_label("map_luts"))
|
||||
{
|
||||
if (abc2 || help_mode) {
|
||||
if (abc2 || help_mode)
|
||||
run("abc", " (only if -abc2)");
|
||||
}
|
||||
std::string techmap_args = asyncprld ? "" : "-map +/ecp5/latches_map.v";
|
||||
if (abc9)
|
||||
techmap_args += " -map +/ecp5/abc9_map.v -max_iter 1";
|
||||
if (!asyncprld || abc9)
|
||||
run("techmap " + techmap_args);
|
||||
if (!asyncprld || help_mode)
|
||||
run("techmap -map +/ecp5/latches_map.v", "(skip if -asyncprld)");
|
||||
|
||||
if (abc9) {
|
||||
run("read_verilog -icells -lib -specify +/abc9_model.v +/ecp5/abc9_model.v");
|
||||
run("read_verilog -icells -lib -specify +/ecp5/abc9_model.v");
|
||||
std::string abc9_opts;
|
||||
if (nowidelut)
|
||||
abc9_opts += " -maxlut 4";
|
||||
|
@ -338,26 +344,29 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
else
|
||||
abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str());
|
||||
if (nowidelut)
|
||||
run("abc9 -maxlut 4 -W 200");
|
||||
else
|
||||
run("abc9 -W 200");
|
||||
run("techmap -map +/ecp5/abc9_unmap.v");
|
||||
abc9_opts += " -maxlut 4";
|
||||
if (dff)
|
||||
abc9_opts += " -dff";
|
||||
run("abc9" + abc9_opts);
|
||||
} else {
|
||||
std::string abc_args = " -dress";
|
||||
if (nowidelut)
|
||||
run("abc -lut 4 -dress");
|
||||
abc_args += " -lut 4";
|
||||
else
|
||||
run("abc -lut 4:7 -dress");
|
||||
abc_args += " -lut 4:7";
|
||||
if (dff)
|
||||
abc_args += " -dff";
|
||||
run("abc" + abc_args);
|
||||
}
|
||||
run("clean");
|
||||
}
|
||||
|
||||
if (check_label("map_cells"))
|
||||
{
|
||||
if (vpr)
|
||||
run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
|
||||
else
|
||||
run("techmap -map +/ecp5/cells_map.v", "(with -D NO_LUT in vpr mode)");
|
||||
|
||||
if (help_mode)
|
||||
run("techmap -map +/ecp5/cells_map.v", "(skip if -vpr)");
|
||||
else if (!vpr)
|
||||
run("techmap -map +/ecp5/cells_map.v");
|
||||
run("opt_lut_ins -tech ecp5");
|
||||
run("clean");
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ techlibs/ice40/brams_init3.vh: techlibs/ice40/brams_init.mk
|
|||
|
||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/arith_map.v))
|
||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_map.v))
|
||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/ff_map.v))
|
||||
$(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))
|
||||
|
|
|
@ -1,33 +1,3 @@
|
|||
module \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule
|
||||
module \$_DFF_P_ (input D, C, output Q); SB_DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule
|
||||
|
||||
module \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
|
||||
module \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
|
||||
|
||||
module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
|
||||
module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
|
||||
|
||||
module \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule
|
||||
module \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule
|
||||
module \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule
|
||||
module \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule
|
||||
|
||||
module \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule
|
||||
module \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule
|
||||
module \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule
|
||||
module \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule
|
||||
|
||||
module \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
|
||||
module \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
|
||||
module \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
|
||||
module \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
|
||||
|
||||
module \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
|
||||
module \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule
|
||||
module \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
|
||||
module \$__DFFE_PP1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule
|
||||
|
||||
`ifndef NO_LUT
|
||||
module \$lut (A, Y);
|
||||
parameter WIDTH = 0;
|
||||
parameter LUT = 0;
|
||||
|
@ -59,4 +29,3 @@ module \$lut (A, Y);
|
|||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
`endif
|
||||
|
|
|
@ -245,6 +245,7 @@ endmodule
|
|||
|
||||
// Positive Edge SiliconBlue FF Cells
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module SB_DFF (
|
||||
output `SB_DFF_REG,
|
||||
input C, D
|
||||
|
@ -280,6 +281,7 @@ module SB_DFF (
|
|||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module SB_DFFE (
|
||||
output `SB_DFF_REG,
|
||||
input C, E, D
|
||||
|
@ -322,6 +324,7 @@ module SB_DFFE (
|
|||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module SB_DFFSR (
|
||||
output `SB_DFF_REG,
|
||||
input C, R, D
|
||||
|
@ -369,6 +372,7 @@ module SB_DFFSR (
|
|||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module SB_DFFR (
|
||||
output `SB_DFF_REG,
|
||||
input C, R, D
|
||||
|
@ -386,7 +390,13 @@ module SB_DFFR (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
|
||||
$setup(negedge R, posedge C, 160);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge R => (Q : 1'b0)) = 599;
|
||||
`else
|
||||
if (R) (R => Q) = 599; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
|
||||
if (!R) (posedge C => (Q : D)) = 540;
|
||||
endspecify
|
||||
|
@ -399,7 +409,13 @@ module SB_DFFR (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
|
||||
$setup(negedge R, posedge C, 235);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge R => (Q : 1'b0)) = 883;
|
||||
`else
|
||||
if (R) (R => Q) = 883; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
|
||||
if (!R) (posedge C => (Q : D)) = 796;
|
||||
endspecify
|
||||
|
@ -412,13 +428,20 @@ module SB_DFFR (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
|
||||
$setup(negedge R, posedge C, 424);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
|
||||
`ifndef YOSYS
|
||||
(posedge R => (Q : 1'b0)) = 1589;
|
||||
`else
|
||||
if (R) (R => Q) = 1589; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
|
||||
if (!R) (posedge C => (Q : D)) = 1391;
|
||||
endspecify
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module SB_DFFSS (
|
||||
output `SB_DFF_REG,
|
||||
input C, S, D
|
||||
|
@ -466,6 +489,7 @@ module SB_DFFSS (
|
|||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module SB_DFFS (
|
||||
output `SB_DFF_REG,
|
||||
input C, S, D
|
||||
|
@ -483,7 +507,13 @@ module SB_DFFS (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
|
||||
$setup(negedge S, posedge C, 160);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge S => (Q : 1'b1)) = 599;
|
||||
`else
|
||||
if (S) (S => Q) = 599; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
|
||||
if (!S) (posedge C => (Q : D)) = 540;
|
||||
endspecify
|
||||
|
@ -496,7 +526,13 @@ module SB_DFFS (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
|
||||
$setup(negedge S, posedge C, 235);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge S => (Q : 1'b1)) = 883;
|
||||
`else
|
||||
if (S) (S => Q) = 883; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
|
||||
if (!S) (posedge C => (Q : D)) = 796;
|
||||
endspecify
|
||||
|
@ -509,13 +545,20 @@ module SB_DFFS (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
|
||||
$setup(negedge S, posedge C, 424);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
|
||||
`ifndef YOSYS
|
||||
(posedge S => (Q : 1'b1)) = 1589;
|
||||
`else
|
||||
if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
|
||||
if (!S) (posedge C => (Q : D)) = 1391;
|
||||
endspecify
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module SB_DFFESR (
|
||||
output `SB_DFF_REG,
|
||||
input C, E, R, D
|
||||
|
@ -571,6 +614,7 @@ module SB_DFFESR (
|
|||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module SB_DFFER (
|
||||
output `SB_DFF_REG,
|
||||
input C, E, R, D
|
||||
|
@ -590,7 +634,13 @@ module SB_DFFER (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
|
||||
$setup(negedge R, posedge C, 160);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge R => (Q : 1'b0)) = 599;
|
||||
`else
|
||||
if (R) (R => Q) = 599; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
|
||||
if (E && !R) (posedge C => (Q : D)) = 540;
|
||||
endspecify
|
||||
|
@ -605,7 +655,13 @@ module SB_DFFER (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
|
||||
$setup(negedge R, posedge C, 235);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge R => (Q : 1'b0)) = 883;
|
||||
`else
|
||||
if (R) (R => Q) = 883; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
|
||||
if (E && !R) (posedge C => (Q : D)) = 796;
|
||||
endspecify
|
||||
|
@ -620,13 +676,20 @@ module SB_DFFER (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
|
||||
$setup(negedge R, posedge C, 424);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
|
||||
`ifndef YOSYS
|
||||
(posedge R => (Q : 1'b0)) = 1589;
|
||||
`else
|
||||
if (R) (R => Q) = 1589; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
|
||||
if (E && !R) (posedge C => (Q : D)) = 1391;
|
||||
endspecify
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module SB_DFFESS (
|
||||
output `SB_DFF_REG,
|
||||
input C, E, S, D
|
||||
|
@ -682,6 +745,7 @@ module SB_DFFESS (
|
|||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module SB_DFFES (
|
||||
output `SB_DFF_REG,
|
||||
input C, E, S, D
|
||||
|
@ -701,7 +765,13 @@ module SB_DFFES (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
|
||||
$setup(posedge S, posedge C, 160);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge S => (Q : 1'b1)) = 599;
|
||||
`else
|
||||
if (S) (S => Q) = 599; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
|
||||
if (E && !S) (posedge C => (Q : D)) = 540;
|
||||
endspecify
|
||||
|
@ -716,7 +786,13 @@ module SB_DFFES (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
|
||||
$setup(posedge S, posedge C, 235);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge S => (Q : 1'b1)) = 883;
|
||||
`else
|
||||
if (S) (S => Q) = 883; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
|
||||
if (E && !S) (posedge C => (Q : D)) = 796;
|
||||
endspecify
|
||||
|
@ -731,7 +807,13 @@ module SB_DFFES (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
|
||||
$setup(posedge S, posedge C, 424);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
|
||||
`ifndef YOSYS
|
||||
(posedge S => (Q : 1'b1)) = 1589;
|
||||
`else
|
||||
if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
|
||||
if (E && !S) (posedge C => (Q : D)) = 1391;
|
||||
endspecify
|
||||
|
@ -740,6 +822,7 @@ endmodule
|
|||
|
||||
// Negative Edge SiliconBlue FF Cells
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module SB_DFFN (
|
||||
output `SB_DFF_REG,
|
||||
input C, D
|
||||
|
@ -775,6 +858,7 @@ module SB_DFFN (
|
|||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module SB_DFFNE (
|
||||
output `SB_DFF_REG,
|
||||
input C, E, D
|
||||
|
@ -817,6 +901,7 @@ module SB_DFFNE (
|
|||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module SB_DFFNSR (
|
||||
output `SB_DFF_REG,
|
||||
input C, R, D
|
||||
|
@ -864,6 +949,7 @@ module SB_DFFNSR (
|
|||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module SB_DFFNR (
|
||||
output `SB_DFF_REG,
|
||||
input C, R, D
|
||||
|
@ -881,7 +967,13 @@ module SB_DFFNR (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
|
||||
$setup(negedge R, negedge C, 160);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge R => (Q : 1'b0)) = 599;
|
||||
`else
|
||||
if (R) (R => Q) = 599; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
|
||||
if (!R) (negedge C => (Q : D)) = 540;
|
||||
endspecify
|
||||
|
@ -894,7 +986,13 @@ module SB_DFFNR (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
|
||||
$setup(negedge R, negedge C, 235);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge R => (Q : 1'b0)) = 883;
|
||||
`else
|
||||
if (R) (R => Q) = 883; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
|
||||
if (!R) (negedge C => (Q : D)) = 796;
|
||||
endspecify
|
||||
|
@ -907,13 +1005,20 @@ module SB_DFFNR (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
|
||||
$setup(negedge R, negedge C, 424);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
|
||||
`ifndef YOSYS
|
||||
(posedge R => (Q : 1'b0)) = 1589;
|
||||
`else
|
||||
if (R) (R => Q) = 1589; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
|
||||
if (!R) (negedge C => (Q : D)) = 1391;
|
||||
endspecify
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module SB_DFFNSS (
|
||||
output `SB_DFF_REG,
|
||||
input C, S, D
|
||||
|
@ -961,6 +1066,7 @@ module SB_DFFNSS (
|
|||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module SB_DFFNS (
|
||||
output `SB_DFF_REG,
|
||||
input C, S, D
|
||||
|
@ -978,7 +1084,13 @@ module SB_DFFNS (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
|
||||
$setup(negedge S, negedge C, 160);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge S => (Q : 1'b1)) = 599;
|
||||
`else
|
||||
if (S) (S => Q) = 599; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
|
||||
if (!S) (negedge C => (Q : D)) = 540;
|
||||
endspecify
|
||||
|
@ -991,7 +1103,13 @@ module SB_DFFNS (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
|
||||
$setup(negedge S, negedge C, 235);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge S => (Q : 1'b1)) = 883;
|
||||
`else
|
||||
if (S) (S => Q) = 883; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
|
||||
if (!S) (negedge C => (Q : D)) = 796;
|
||||
endspecify
|
||||
|
@ -1004,13 +1122,20 @@ module SB_DFFNS (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
|
||||
$setup(negedge S, negedge C, 424);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
|
||||
`ifndef YOSYS
|
||||
(posedge S => (Q : 1'b1)) = 1589;
|
||||
`else
|
||||
if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
|
||||
if (!S) (negedge C => (Q : D)) = 1391;
|
||||
endspecify
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module SB_DFFNESR (
|
||||
output `SB_DFF_REG,
|
||||
input C, E, R, D
|
||||
|
@ -1066,6 +1191,7 @@ module SB_DFFNESR (
|
|||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module SB_DFFNER (
|
||||
output `SB_DFF_REG,
|
||||
input C, E, R, D
|
||||
|
@ -1085,7 +1211,13 @@ module SB_DFFNER (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
|
||||
$setup(R, negedge C, 2160);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge R => (Q : 1'b0)) = 599;
|
||||
`else
|
||||
if (R) (R => Q) = 599; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
|
||||
if (E && !R) (negedge C => (Q : D)) = 540;
|
||||
endspecify
|
||||
|
@ -1100,7 +1232,13 @@ module SB_DFFNER (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
|
||||
$setup(R, negedge C, 235);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge R => (Q : 1'b0)) = 883;
|
||||
`else
|
||||
if (R) (R => Q) = 883; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
|
||||
if (E && !R) (negedge C => (Q : D)) = 796;
|
||||
endspecify
|
||||
|
@ -1115,13 +1253,20 @@ module SB_DFFNER (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
|
||||
$setup(negedge R, negedge C, 424);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
|
||||
`ifndef YOSYS
|
||||
(posedge R => (Q : 1'b0)) = 1589;
|
||||
`else
|
||||
if (R) (R => Q) = 1589; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
|
||||
if (E && !R) (negedge C => (Q : D)) = 1391;
|
||||
endspecify
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module SB_DFFNESS (
|
||||
output `SB_DFF_REG,
|
||||
input C, E, S, D
|
||||
|
@ -1177,6 +1322,7 @@ module SB_DFFNESS (
|
|||
`endif
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module SB_DFFNES (
|
||||
output `SB_DFF_REG,
|
||||
input C, E, S, D
|
||||
|
@ -1196,7 +1342,14 @@ module SB_DFFNES (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
|
||||
$setup(negedge S, negedge C, 160);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge S => (Q : 1'b1)) = 599;
|
||||
`else
|
||||
if (S) (S => Q) = 599; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
|
||||
if (E && !S) (negedge C => (Q : D)) = 540;
|
||||
endspecify
|
||||
|
@ -1211,7 +1364,13 @@ module SB_DFFNES (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
|
||||
$setup(negedge S, negedge C, 235);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
|
||||
`ifndef YOSYS
|
||||
(posedge S => (Q : 1'b1)) = 883;
|
||||
`else
|
||||
if (S) (S => Q) = 883; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
|
||||
if (E && !S) (negedge C => (Q : D)) = 796;
|
||||
endspecify
|
||||
|
@ -1226,7 +1385,13 @@ module SB_DFFNES (
|
|||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
|
||||
$setup(negedge S, negedge C, 424);
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
|
||||
`ifndef YOSYS
|
||||
(posedge S => (Q : 1'b1)) = 1589;
|
||||
`else
|
||||
if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
|
||||
if (E && !S) (negedge C => (Q : D)) = 1391;
|
||||
endspecify
|
||||
|
@ -2723,6 +2888,7 @@ module SB_IO_OD (
|
|||
`endif
|
||||
endmodule
|
||||
|
||||
//(* abc9_box, lib_whitebox *) // TODO
|
||||
module SB_MAC16 (
|
||||
input CLK, CE,
|
||||
input [15:0] C, A, B, D,
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
module \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule
|
||||
module \$_DFF_P_ (input D, C, output Q); SB_DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule
|
||||
|
||||
module \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
|
||||
module \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
|
||||
|
||||
module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
|
||||
module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
|
||||
|
||||
module \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule
|
||||
module \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule
|
||||
module \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule
|
||||
module \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule
|
||||
|
||||
module \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule
|
||||
module \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule
|
||||
module \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule
|
||||
module \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule
|
||||
|
||||
module \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
|
||||
module \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
|
||||
module \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
|
||||
module \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
|
||||
|
||||
module \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
|
||||
module \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule
|
||||
module \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
|
||||
module \$__DFFE_PP1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule
|
|
@ -71,6 +71,9 @@ struct SynthIce40Pass : public ScriptPass
|
|||
log(" -noflatten\n");
|
||||
log(" do not flatten design before synthesis\n");
|
||||
log("\n");
|
||||
log(" -dff\n");
|
||||
log(" run 'abc'/'abc9' with -dff option\n");
|
||||
log("\n");
|
||||
log(" -retime\n");
|
||||
log(" run 'abc' with '-dff -D 1' options\n");
|
||||
log("\n");
|
||||
|
@ -113,7 +116,7 @@ struct SynthIce40Pass : public ScriptPass
|
|||
}
|
||||
|
||||
string top_opt, blif_file, edif_file, json_file, device_opt;
|
||||
bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr, abc9, flowmap;
|
||||
bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr, abc9, dff, flowmap;
|
||||
int min_ce_use;
|
||||
|
||||
void clear_flags() YS_OVERRIDE
|
||||
|
@ -221,6 +224,10 @@ struct SynthIce40Pass : public ScriptPass
|
|||
abc9 = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-dff") {
|
||||
dff = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-device" && argidx+1 < args.size()) {
|
||||
device_opt = args[++argidx];
|
||||
continue;
|
||||
|
@ -354,7 +361,9 @@ struct SynthIce40Pass : public ScriptPass
|
|||
run(stringf("dff2dffe -unmap-mince %d", min_ce_use));
|
||||
run("simplemap t:$dff");
|
||||
}
|
||||
run("techmap -D NO_LUT -D NO_ADDER -map +/ice40/cells_map.v");
|
||||
if ((abc9 && dff) || help_mode)
|
||||
run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "(only if -abc9 and -dff");
|
||||
run("techmap -map +/ice40/ff_map.v");
|
||||
run("opt_expr -mux_undef");
|
||||
run("simplemap");
|
||||
run("ice40_ffinit");
|
||||
|
@ -378,7 +387,7 @@ struct SynthIce40Pass : public ScriptPass
|
|||
}
|
||||
if (!noabc) {
|
||||
if (abc9) {
|
||||
run("read_verilog " + define + " -icells -lib -specify +/abc9_model.v +/ice40/abc9_model.v");
|
||||
run("read_verilog " + define + " -icells -lib -specify +/ice40/abc9_model.v");
|
||||
std::string abc9_opts;
|
||||
std::string k = "synth_ice40.abc9.W";
|
||||
if (active_design && active_design->scratchpad.count(k))
|
||||
|
@ -387,24 +396,25 @@ struct SynthIce40Pass : public ScriptPass
|
|||
k = stringf("synth_ice40.abc9.%s.W", device_opt.c_str());
|
||||
abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str());
|
||||
}
|
||||
if (dff)
|
||||
abc9_opts += " -dff";
|
||||
run("abc9 " + abc9_opts);
|
||||
}
|
||||
else
|
||||
run("abc -dress -lut 4", "(skip if -noabc)");
|
||||
run(stringf("abc -dress -lut 4 %s", dff ? "-dff" : ""), "(skip if -noabc)");
|
||||
}
|
||||
run("ice40_wrapcarry -unwrap");
|
||||
run("techmap -D NO_LUT -map +/ice40/cells_map.v");
|
||||
run("techmap -map +/ice40/ff_map.v");
|
||||
run("clean");
|
||||
run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0");
|
||||
}
|
||||
|
||||
if (check_label("map_cells"))
|
||||
{
|
||||
if (vpr)
|
||||
run("techmap -D NO_LUT -map +/ice40/cells_map.v");
|
||||
else
|
||||
run("techmap -map +/ice40/cells_map.v", "(with -D NO_LUT in vpr mode)");
|
||||
|
||||
if (help_mode)
|
||||
run("techmap -map +/ice40/cells_map.v", "(skip if -vpr)");
|
||||
else if (!vpr)
|
||||
run("techmap -map +/ice40/cells_map.v");
|
||||
run("clean");
|
||||
}
|
||||
|
||||
|
|
|
@ -209,7 +209,6 @@ struct SynthIntelALMPass : public ScriptPass {
|
|||
}
|
||||
|
||||
if (check_label("map_luts")) {
|
||||
run("read_verilog -icells -specify -lib +/abc9_model.v");
|
||||
run("abc9 -maxlut 6 -W 200");
|
||||
run("techmap -map +/intel_alm/common/alm_map.v");
|
||||
run("opt -fast");
|
||||
|
|
|
@ -54,8 +54,6 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc5v_dsp_map.v))
|
|||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_dsp_map.v))
|
||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_dsp_map.v))
|
||||
|
||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_map.v))
|
||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_unmap.v))
|
||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_model.v))
|
||||
|
||||
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh))
|
||||
|
|
|
@ -1,786 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// The following techmapping rules are intended to be run (with -max_iter 1)
|
||||
// before invoking the `abc9` pass in order to transform the design into
|
||||
// a format that it understands.
|
||||
|
||||
`ifdef DFF_MODE
|
||||
// For example, (complex) flip-flops are expected to be described as an
|
||||
// combinatorial box (containing all control logic such as clock enable
|
||||
// or synchronous resets) followed by a basic D-Q flop.
|
||||
// Yosys will automatically analyse the simulation model (described in
|
||||
// cells_sim.v) and detach any $_DFF_P_ or $_DFF_N_ cells present in
|
||||
// order to extract the combinatorial control logic left behind.
|
||||
// Specifically, a simulation model similar to the one below:
|
||||
//
|
||||
// ++===================================++
|
||||
// || Sim model ||
|
||||
// || /\/\/\/\ ||
|
||||
// D -->>-----< > +------+ ||
|
||||
// R -->>-----< Comb. > |$_DFF_| ||
|
||||
// CE -->>-----< logic >-----| [NP]_|---+---->>-- Q
|
||||
// || +--< > +------+ | ||
|
||||
// || | \/\/\/\/ | ||
|
||||
// || | | ||
|
||||
// || +----------------------------+ ||
|
||||
// || ||
|
||||
// ++===================================++
|
||||
//
|
||||
// is transformed into:
|
||||
//
|
||||
// ++==================++
|
||||
// || Comb box ||
|
||||
// || ||
|
||||
// || /\/\/\/\ ||
|
||||
// D -->>-----< > ||
|
||||
// R -->>-----< Comb. > || +-----------+
|
||||
// CE -->>-----< logic >--->>-- $Q --|$__ABC9_FF_|--+-->> Q
|
||||
// abc9_ff.Q +-->>-----< > || +-----------+ |
|
||||
// | || \/\/\/\/ || |
|
||||
// | || || |
|
||||
// | ++==================++ |
|
||||
// | |
|
||||
// +-----------------------------------------------+
|
||||
//
|
||||
// The purpose of the following FD* rules are to wrap the flop with:
|
||||
// (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9
|
||||
// the connectivity of its basic D-Q flop
|
||||
// (b) an optional $__ABC9_ASYNC_ cell in front of $__ABC_FF_'s output to
|
||||
// capture asynchronous behaviour
|
||||
// (c) a special abc9_ff.clock wire to capture its clock domain and polarity
|
||||
// (indicated to `abc9' so that it only performs sequential synthesis
|
||||
// (with reachability analysis) correctly on one domain at a time)
|
||||
// (d) an (* abc9_init *) attribute on the $__ABC9_FF_ cell capturing its
|
||||
// initial state
|
||||
// NOTE: in order to perform sequential synthesis, `abc9' requires that
|
||||
// the initial value of all flops be zero
|
||||
// (e) a special _TECHMAP_REPLACE_.abc9_ff.Q wire that will be used for feedback
|
||||
// into the (combinatorial) FD* cell to facilitate clock-enable behaviour
|
||||
|
||||
module FDRE (output Q, (* techmap_autopurge *) 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;
|
||||
parameter [0:0] IS_R_INVERTED = 1'b0;
|
||||
wire QQ, $Q;
|
||||
generate if (INIT == 1'b1) begin
|
||||
assign Q = ~QQ;
|
||||
FDSE #(
|
||||
.INIT(1'b0),
|
||||
.IS_C_INVERTED(IS_C_INVERTED),
|
||||
.IS_D_INVERTED(IS_D_INVERTED),
|
||||
.IS_S_INVERTED(IS_R_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(~D), .Q($Q), .C(C), .CE(CE), .S(R)
|
||||
);
|
||||
end
|
||||
else begin
|
||||
assign Q = QQ;
|
||||
FDRE #(
|
||||
.INIT(1'b0),
|
||||
.IS_C_INVERTED(IS_C_INVERTED),
|
||||
.IS_D_INVERTED(IS_D_INVERTED),
|
||||
.IS_R_INVERTED(IS_R_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(D), .Q($Q), .C(C), .CE(CE), .R(R)
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
(* abc9_init = 1'b0 *)
|
||||
$__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ));
|
||||
|
||||
// Special signals
|
||||
wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED};
|
||||
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ;
|
||||
endmodule
|
||||
module FDRE_1 (output Q, (* techmap_autopurge *) input C, CE, D, R);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
wire QQ, $Q;
|
||||
generate if (INIT == 1'b1) begin
|
||||
assign Q = ~QQ;
|
||||
FDSE_1 #(
|
||||
.INIT(1'b0)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(~D), .Q($Q), .C(C), .CE(CE), .S(R)
|
||||
);
|
||||
end
|
||||
else begin
|
||||
assign Q = QQ;
|
||||
FDRE_1 #(
|
||||
.INIT(1'b0)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(D), .Q($Q), .C(C), .CE(CE), .R(R)
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
(* abc9_init = 1'b0 *)
|
||||
$__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ));
|
||||
|
||||
// Special signals
|
||||
wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */};
|
||||
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ;
|
||||
endmodule
|
||||
|
||||
module FDSE (output Q, (* techmap_autopurge *) input C, CE, D, S);
|
||||
parameter [0:0] INIT = 1'b1;
|
||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_D_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_S_INVERTED = 1'b0;
|
||||
wire QQ, $Q;
|
||||
generate if (INIT == 1'b1) begin
|
||||
assign Q = ~QQ;
|
||||
FDRE #(
|
||||
.INIT(1'b0),
|
||||
.IS_C_INVERTED(IS_C_INVERTED),
|
||||
.IS_D_INVERTED(IS_D_INVERTED),
|
||||
.IS_R_INVERTED(IS_S_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(~D), .Q($Q), .C(C), .CE(CE), .R(S)
|
||||
);
|
||||
end
|
||||
else begin
|
||||
assign Q = QQ;
|
||||
FDSE #(
|
||||
.INIT(1'b0),
|
||||
.IS_C_INVERTED(IS_C_INVERTED),
|
||||
.IS_D_INVERTED(IS_D_INVERTED),
|
||||
.IS_S_INVERTED(IS_S_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(D), .Q($Q), .C(C), .CE(CE), .S(S)
|
||||
);
|
||||
end endgenerate
|
||||
(* abc9_init = 1'b0 *)
|
||||
$__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ));
|
||||
|
||||
// Special signals
|
||||
wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED};
|
||||
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ;
|
||||
endmodule
|
||||
module FDSE_1 (output Q, (* techmap_autopurge *) input C, CE, D, S);
|
||||
parameter [0:0] INIT = 1'b1;
|
||||
wire QQ, $Q;
|
||||
generate if (INIT == 1'b1) begin
|
||||
assign Q = ~QQ;
|
||||
FDRE_1 #(
|
||||
.INIT(1'b0)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(~D), .Q($Q), .C(C), .CE(CE), .R(S)
|
||||
);
|
||||
end
|
||||
else begin
|
||||
assign Q = QQ;
|
||||
FDSE_1 #(
|
||||
.INIT(1'b0)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(D), .Q($Q), .C(C), .CE(CE), .S(S)
|
||||
);
|
||||
end endgenerate
|
||||
(* abc9_init = 1'b0 *)
|
||||
$__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ));
|
||||
|
||||
// Special signals
|
||||
wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */};
|
||||
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ;
|
||||
endmodule
|
||||
|
||||
module FDCE (output Q, (* techmap_autopurge *) 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;
|
||||
parameter [0:0] IS_CLR_INVERTED = 1'b0;
|
||||
wire QQ, $Q, $QQ;
|
||||
generate if (INIT == 1'b1) begin
|
||||
assign Q = ~QQ;
|
||||
FDPE #(
|
||||
.INIT(1'b0),
|
||||
.IS_C_INVERTED(IS_C_INVERTED),
|
||||
.IS_D_INVERTED(IS_D_INVERTED),
|
||||
.IS_PRE_INVERTED(IS_CLR_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR)
|
||||
// ^^^ Note that async
|
||||
// control is not directly
|
||||
// supported by abc9 but its
|
||||
// behaviour is captured by
|
||||
// $__ABC9_ASYNC1 below
|
||||
);
|
||||
// Since this is an async flop, async behaviour is dealt with here
|
||||
$__ABC9_ASYNC1 abc_async (.A($QQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ));
|
||||
end
|
||||
else begin
|
||||
assign Q = QQ;
|
||||
FDCE #(
|
||||
.INIT(1'b0),
|
||||
.IS_C_INVERTED(IS_C_INVERTED),
|
||||
.IS_D_INVERTED(IS_D_INVERTED),
|
||||
.IS_CLR_INVERTED(IS_CLR_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR)
|
||||
// ^^^ Note that async
|
||||
// control is not directly
|
||||
// supported by abc9 but its
|
||||
// behaviour is captured by
|
||||
// $__ABC9_ASYNC0 below
|
||||
);
|
||||
// Since this is an async flop, async behaviour is dealt with here
|
||||
$__ABC9_ASYNC0 abc_async (.A($QQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ));
|
||||
end endgenerate
|
||||
(* abc9_init = 1'b0 *)
|
||||
$__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ));
|
||||
|
||||
// Special signals
|
||||
wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED};
|
||||
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ;
|
||||
endmodule
|
||||
module FDCE_1 (output Q, (* techmap_autopurge *) input C, CE, D, CLR);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
wire QQ, $Q, $QQ;
|
||||
generate if (INIT == 1'b1) begin
|
||||
assign Q = ~QQ;
|
||||
FDPE_1 #(
|
||||
.INIT(1'b0)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR)
|
||||
// ^^^ Note that async
|
||||
// control is not directly
|
||||
// supported by abc9 but its
|
||||
// behaviour is captured by
|
||||
// $__ABC9_ASYNC1 below
|
||||
);
|
||||
$__ABC9_ASYNC1 abc_async (.A($QQ), .S(CLR), .Y(QQ));
|
||||
end
|
||||
else begin
|
||||
assign Q = QQ;
|
||||
FDCE_1 #(
|
||||
.INIT(1'b0)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR)
|
||||
// ^^^ Note that async
|
||||
// control is not directly
|
||||
// supported by abc9 but its
|
||||
// behaviour is captured by
|
||||
// $__ABC9_ASYNC0 below
|
||||
);
|
||||
$__ABC9_ASYNC0 abc_async (.A($QQ), .S(CLR), .Y(QQ));
|
||||
end endgenerate
|
||||
(* abc9_init = 1'b0 *)
|
||||
$__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ));
|
||||
|
||||
// Special signals
|
||||
wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */};
|
||||
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ;
|
||||
endmodule
|
||||
|
||||
module FDPE (output Q, (* techmap_autopurge *) input C, CE, D, PRE);
|
||||
parameter [0:0] INIT = 1'b1;
|
||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_D_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_PRE_INVERTED = 1'b0;
|
||||
wire QQ, $Q, $QQ;
|
||||
generate if (INIT == 1'b1) begin
|
||||
assign Q = ~QQ;
|
||||
FDCE #(
|
||||
.INIT(1'b0),
|
||||
.IS_C_INVERTED(IS_C_INVERTED),
|
||||
.IS_D_INVERTED(IS_D_INVERTED),
|
||||
.IS_CLR_INVERTED(IS_PRE_INVERTED),
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE)
|
||||
// ^^^ Note that async
|
||||
// control is not directly
|
||||
// supported by abc9 but its
|
||||
// behaviour is captured by
|
||||
// $__ABC9_ASYNC0 below
|
||||
);
|
||||
$__ABC9_ASYNC0 abc_async (.A($QQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ));
|
||||
end
|
||||
else begin
|
||||
assign Q = QQ;
|
||||
FDPE #(
|
||||
.INIT(1'b0),
|
||||
.IS_C_INVERTED(IS_C_INVERTED),
|
||||
.IS_D_INVERTED(IS_D_INVERTED),
|
||||
.IS_PRE_INVERTED(IS_PRE_INVERTED),
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE)
|
||||
// ^^^ Note that async
|
||||
// control is not directly
|
||||
// supported by abc9 but its
|
||||
// behaviour is captured by
|
||||
// $__ABC9_ASYNC1 below
|
||||
);
|
||||
$__ABC9_ASYNC1 abc_async (.A($QQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ));
|
||||
end endgenerate
|
||||
(* abc9_init = 1'b0 *)
|
||||
$__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ));
|
||||
|
||||
// Special signals
|
||||
wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED};
|
||||
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ;
|
||||
endmodule
|
||||
module FDPE_1 (output Q, (* techmap_autopurge *) input C, CE, D, PRE);
|
||||
parameter [0:0] INIT = 1'b1;
|
||||
wire QQ, $Q, $QQ;
|
||||
generate if (INIT == 1'b1) begin
|
||||
assign Q = ~QQ;
|
||||
FDCE_1 #(
|
||||
.INIT(1'b0)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE)
|
||||
// ^^^ Note that async
|
||||
// control is not directly
|
||||
// supported by abc9 but its
|
||||
// behaviour is captured by
|
||||
// $__ABC9_ASYNC0 below
|
||||
);
|
||||
$__ABC9_ASYNC0 abc_async (.A($QQ), .S(PRE), .Y(QQ));
|
||||
end
|
||||
else begin
|
||||
assign Q = QQ;
|
||||
FDPE_1 #(
|
||||
.INIT(1'b0)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE)
|
||||
// ^^^ Note that async
|
||||
// control is not directly
|
||||
// supported by abc9 but its
|
||||
// behaviour is captured by
|
||||
// $__ABC9_ASYNC1 below
|
||||
);
|
||||
$__ABC9_ASYNC1 abc_async (.A($QQ), .S(PRE), .Y(QQ));
|
||||
end endgenerate
|
||||
(* abc9_init = 1'b0 *)
|
||||
$__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ));
|
||||
|
||||
// Special signals
|
||||
wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */};
|
||||
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ;
|
||||
endmodule
|
||||
`endif
|
||||
|
||||
// Attach a (combinatorial) black-box onto the output
|
||||
// of thes LUTRAM primitives to capture their
|
||||
// asynchronous read behaviour
|
||||
module RAM32X1D (
|
||||
output DPO, SPO,
|
||||
(* techmap_autopurge *) input D,
|
||||
(* techmap_autopurge *) input WCLK,
|
||||
(* techmap_autopurge *) input WE,
|
||||
(* techmap_autopurge *) input A0, A1, A2, A3, A4,
|
||||
(* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
|
||||
);
|
||||
parameter INIT = 32'h0;
|
||||
parameter IS_WCLK_INVERTED = 1'b0;
|
||||
wire $DPO, $SPO;
|
||||
RAM32X1D #(
|
||||
.INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.DPO($DPO), .SPO($SPO),
|
||||
.D(D), .WCLK(WCLK), .WE(WE),
|
||||
.A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4),
|
||||
.DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4)
|
||||
);
|
||||
$__ABC9_RAM6 spo (.A($SPO), .S({1'b1, A4, A3, A2, A1, A0}), .Y(SPO));
|
||||
$__ABC9_RAM6 dpo (.A($DPO), .S({1'b1, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO));
|
||||
endmodule
|
||||
|
||||
module RAM64X1D (
|
||||
output DPO, SPO,
|
||||
(* techmap_autopurge *) input D,
|
||||
(* techmap_autopurge *) input WCLK,
|
||||
(* techmap_autopurge *) input WE,
|
||||
(* techmap_autopurge *) input A0, A1, A2, A3, A4, A5,
|
||||
(* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
|
||||
);
|
||||
parameter INIT = 64'h0;
|
||||
parameter IS_WCLK_INVERTED = 1'b0;
|
||||
wire $DPO, $SPO;
|
||||
RAM64X1D #(
|
||||
.INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.DPO($DPO), .SPO($SPO),
|
||||
.D(D), .WCLK(WCLK), .WE(WE),
|
||||
.A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .A5(A5),
|
||||
.DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4), .DPRA5(DPRA5)
|
||||
);
|
||||
$__ABC9_RAM6 spo (.A($SPO), .S({A5, A4, A3, A2, A1, A0}), .Y(SPO));
|
||||
$__ABC9_RAM6 dpo (.A($DPO), .S({DPRA5, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO));
|
||||
endmodule
|
||||
|
||||
module RAM128X1D (
|
||||
output DPO, SPO,
|
||||
(* techmap_autopurge *) input D,
|
||||
(* techmap_autopurge *) input WCLK,
|
||||
(* techmap_autopurge *) input WE,
|
||||
(* techmap_autopurge *) input [6:0] A, DPRA
|
||||
);
|
||||
parameter INIT = 128'h0;
|
||||
parameter IS_WCLK_INVERTED = 1'b0;
|
||||
wire $DPO, $SPO;
|
||||
RAM128X1D #(
|
||||
.INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.DPO($DPO), .SPO($SPO),
|
||||
.D(D), .WCLK(WCLK), .WE(WE),
|
||||
.A(A),
|
||||
.DPRA(DPRA)
|
||||
);
|
||||
$__ABC9_RAM7 spo (.A($SPO), .S(A), .Y(SPO));
|
||||
$__ABC9_RAM7 dpo (.A($DPO), .S(DPRA), .Y(DPO));
|
||||
endmodule
|
||||
|
||||
module RAM32M (
|
||||
output [1:0] DOA,
|
||||
output [1:0] DOB,
|
||||
output [1:0] DOC,
|
||||
output [1:0] DOD,
|
||||
(* techmap_autopurge *) input [4:0] ADDRA,
|
||||
(* techmap_autopurge *) input [4:0] ADDRB,
|
||||
(* techmap_autopurge *) input [4:0] ADDRC,
|
||||
(* techmap_autopurge *) input [4:0] ADDRD,
|
||||
(* techmap_autopurge *) input [1:0] DIA,
|
||||
(* techmap_autopurge *) input [1:0] DIB,
|
||||
(* techmap_autopurge *) input [1:0] DIC,
|
||||
(* techmap_autopurge *) input [1:0] DID,
|
||||
(* techmap_autopurge *) input WCLK,
|
||||
(* techmap_autopurge *) input WE
|
||||
);
|
||||
parameter [63:0] INIT_A = 64'h0000000000000000;
|
||||
parameter [63:0] INIT_B = 64'h0000000000000000;
|
||||
parameter [63:0] INIT_C = 64'h0000000000000000;
|
||||
parameter [63:0] INIT_D = 64'h0000000000000000;
|
||||
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
||||
wire [1:0] $DOA, $DOB, $DOC, $DOD;
|
||||
RAM32M #(
|
||||
.INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D),
|
||||
.IS_WCLK_INVERTED(IS_WCLK_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.DOA($DOA), .DOB($DOB), .DOC($DOC), .DOD($DOD),
|
||||
.WCLK(WCLK), .WE(WE),
|
||||
.ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD),
|
||||
.DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID)
|
||||
);
|
||||
$__ABC9_RAM6 doa0 (.A($DOA[0]), .S({1'b1, ADDRA}), .Y(DOA[0]));
|
||||
$__ABC9_RAM6 doa1 (.A($DOA[1]), .S({1'b1, ADDRA}), .Y(DOA[1]));
|
||||
$__ABC9_RAM6 dob0 (.A($DOB[0]), .S({1'b1, ADDRB}), .Y(DOB[0]));
|
||||
$__ABC9_RAM6 dob1 (.A($DOB[1]), .S({1'b1, ADDRB}), .Y(DOB[1]));
|
||||
$__ABC9_RAM6 doc0 (.A($DOC[0]), .S({1'b1, ADDRC}), .Y(DOC[0]));
|
||||
$__ABC9_RAM6 doc1 (.A($DOC[1]), .S({1'b1, ADDRC}), .Y(DOC[1]));
|
||||
$__ABC9_RAM6 dod0 (.A($DOD[0]), .S({1'b1, ADDRD}), .Y(DOD[0]));
|
||||
$__ABC9_RAM6 dod1 (.A($DOD[1]), .S({1'b1, ADDRD}), .Y(DOD[1]));
|
||||
endmodule
|
||||
|
||||
module RAM64M (
|
||||
output DOA,
|
||||
output DOB,
|
||||
output DOC,
|
||||
output DOD,
|
||||
(* techmap_autopurge *) input [5:0] ADDRA,
|
||||
(* techmap_autopurge *) input [5:0] ADDRB,
|
||||
(* techmap_autopurge *) input [5:0] ADDRC,
|
||||
(* techmap_autopurge *) input [5:0] ADDRD,
|
||||
(* techmap_autopurge *) input DIA,
|
||||
(* techmap_autopurge *) input DIB,
|
||||
(* techmap_autopurge *) input DIC,
|
||||
(* techmap_autopurge *) input DID,
|
||||
(* techmap_autopurge *) input WCLK,
|
||||
(* techmap_autopurge *) input WE
|
||||
);
|
||||
parameter [63:0] INIT_A = 64'h0000000000000000;
|
||||
parameter [63:0] INIT_B = 64'h0000000000000000;
|
||||
parameter [63:0] INIT_C = 64'h0000000000000000;
|
||||
parameter [63:0] INIT_D = 64'h0000000000000000;
|
||||
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
||||
wire $DOA, $DOB, $DOC, $DOD;
|
||||
RAM64M #(
|
||||
.INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D),
|
||||
.IS_WCLK_INVERTED(IS_WCLK_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.DOA($DOA), .DOB($DOB), .DOC($DOC), .DOD($DOD),
|
||||
.WCLK(WCLK), .WE(WE),
|
||||
.ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD),
|
||||
.DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID)
|
||||
);
|
||||
$__ABC9_RAM6 doa (.A($DOA), .S(ADDRA), .Y(DOA));
|
||||
$__ABC9_RAM6 dob (.A($DOB), .S(ADDRB), .Y(DOB));
|
||||
$__ABC9_RAM6 doc (.A($DOC), .S(ADDRC), .Y(DOC));
|
||||
$__ABC9_RAM6 dod (.A($DOD), .S(ADDRD), .Y(DOD));
|
||||
endmodule
|
||||
|
||||
module SRL16 (
|
||||
output Q,
|
||||
(* techmap_autopurge *) input A0, A1, A2, A3, CLK, D
|
||||
);
|
||||
parameter [15:0] INIT = 16'h0000;
|
||||
wire $Q;
|
||||
SRL16 #(
|
||||
.INIT(INIT),
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.Q($Q),
|
||||
.A0(A0), .A1(A1), .A2(A2), .A3(A3), .CLK(CLK), .D(D)
|
||||
);
|
||||
$__ABC9_RAM6 q (.A($Q), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q));
|
||||
endmodule
|
||||
|
||||
module SRL16E (
|
||||
output Q,
|
||||
(* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D
|
||||
);
|
||||
parameter [15:0] INIT = 16'h0000;
|
||||
parameter [0:0] IS_CLK_INVERTED = 1'b0;
|
||||
wire $Q;
|
||||
SRL16E #(
|
||||
.INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.Q($Q),
|
||||
.A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D)
|
||||
);
|
||||
$__ABC9_RAM6 q (.A($Q), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q));
|
||||
endmodule
|
||||
|
||||
module SRLC16 (
|
||||
output Q, Q15,
|
||||
(* techmap_autopurge *) input A0, A1, A2, A3, CLK, D
|
||||
);
|
||||
parameter [15:0] INIT = 16'h0000;
|
||||
wire $Q;
|
||||
SRLC16 #(
|
||||
.INIT(INIT),
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.Q($Q), .Q(Q15),
|
||||
.A0(A0), .A1(A1), .A2(A2), .A3(A3), .CLK(CLK), .D(D)
|
||||
);
|
||||
$__ABC9_RAM6 q (.A($Q), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q));
|
||||
endmodule
|
||||
|
||||
module SRLC16E (
|
||||
output Q, Q15,
|
||||
(* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D
|
||||
);
|
||||
parameter [15:0] INIT = 16'h0000;
|
||||
parameter [0:0] IS_CLK_INVERTED = 1'b0;
|
||||
wire $Q;
|
||||
SRLC16E #(
|
||||
.INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.Q($Q), .Q(Q15),
|
||||
.A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D)
|
||||
);
|
||||
$__ABC9_RAM6 q (.A($Q), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q));
|
||||
endmodule
|
||||
|
||||
module SRLC32E (
|
||||
output Q,
|
||||
output Q31,
|
||||
(* techmap_autopurge *) input [4:0] A,
|
||||
(* techmap_autopurge *) input CE, CLK, D
|
||||
);
|
||||
parameter [31:0] INIT = 32'h00000000;
|
||||
parameter [0:0] IS_CLK_INVERTED = 1'b0;
|
||||
wire $Q;
|
||||
SRLC32E #(
|
||||
.INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.Q($Q), .Q31(Q31),
|
||||
.A(A), .CE(CE), .CLK(CLK), .D(D)
|
||||
);
|
||||
$__ABC9_RAM6 q (.A($Q), .S({1'b1, A}), .Y(Q));
|
||||
endmodule
|
||||
|
||||
module DSP48E1 (
|
||||
(* techmap_autopurge *) output [29:0] ACOUT,
|
||||
(* techmap_autopurge *) output [17:0] BCOUT,
|
||||
(* techmap_autopurge *) output reg CARRYCASCOUT,
|
||||
(* techmap_autopurge *) output reg [3:0] CARRYOUT,
|
||||
(* techmap_autopurge *) output reg MULTSIGNOUT,
|
||||
(* techmap_autopurge *) output OVERFLOW,
|
||||
(* techmap_autopurge *) output reg signed [47:0] P,
|
||||
(* techmap_autopurge *) output PATTERNBDETECT,
|
||||
(* techmap_autopurge *) output PATTERNDETECT,
|
||||
(* techmap_autopurge *) output [47:0] PCOUT,
|
||||
(* techmap_autopurge *) output UNDERFLOW,
|
||||
(* techmap_autopurge *) input signed [29:0] A,
|
||||
(* techmap_autopurge *) input [29:0] ACIN,
|
||||
(* techmap_autopurge *) input [3:0] ALUMODE,
|
||||
(* techmap_autopurge *) input signed [17:0] B,
|
||||
(* techmap_autopurge *) input [17:0] BCIN,
|
||||
(* techmap_autopurge *) input [47:0] C,
|
||||
(* techmap_autopurge *) input CARRYCASCIN,
|
||||
(* techmap_autopurge *) input CARRYIN,
|
||||
(* techmap_autopurge *) input [2:0] CARRYINSEL,
|
||||
(* techmap_autopurge *) input CEA1,
|
||||
(* techmap_autopurge *) input CEA2,
|
||||
(* techmap_autopurge *) input CEAD,
|
||||
(* techmap_autopurge *) input CEALUMODE,
|
||||
(* techmap_autopurge *) input CEB1,
|
||||
(* techmap_autopurge *) input CEB2,
|
||||
(* techmap_autopurge *) input CEC,
|
||||
(* techmap_autopurge *) input CECARRYIN,
|
||||
(* techmap_autopurge *) input CECTRL,
|
||||
(* techmap_autopurge *) input CED,
|
||||
(* techmap_autopurge *) input CEINMODE,
|
||||
(* techmap_autopurge *) input CEM,
|
||||
(* techmap_autopurge *) input CEP,
|
||||
(* techmap_autopurge *) input CLK,
|
||||
(* techmap_autopurge *) input [24:0] D,
|
||||
(* techmap_autopurge *) input [4:0] INMODE,
|
||||
(* techmap_autopurge *) input MULTSIGNIN,
|
||||
(* techmap_autopurge *) input [6:0] OPMODE,
|
||||
(* techmap_autopurge *) input [47:0] PCIN,
|
||||
(* techmap_autopurge *) input RSTA,
|
||||
(* techmap_autopurge *) input RSTALLCARRYIN,
|
||||
(* techmap_autopurge *) input RSTALUMODE,
|
||||
(* techmap_autopurge *) input RSTB,
|
||||
(* techmap_autopurge *) input RSTC,
|
||||
(* techmap_autopurge *) input RSTCTRL,
|
||||
(* techmap_autopurge *) input RSTD,
|
||||
(* techmap_autopurge *) input RSTINMODE,
|
||||
(* techmap_autopurge *) input RSTM,
|
||||
(* techmap_autopurge *) input RSTP
|
||||
);
|
||||
parameter integer ACASCREG = 1;
|
||||
parameter integer ADREG = 1;
|
||||
parameter integer ALUMODEREG = 1;
|
||||
parameter integer AREG = 1;
|
||||
parameter AUTORESET_PATDET = "NO_RESET";
|
||||
parameter A_INPUT = "DIRECT";
|
||||
parameter integer BCASCREG = 1;
|
||||
parameter integer BREG = 1;
|
||||
parameter B_INPUT = "DIRECT";
|
||||
parameter integer CARRYINREG = 1;
|
||||
parameter integer CARRYINSELREG = 1;
|
||||
parameter integer CREG = 1;
|
||||
parameter integer DREG = 1;
|
||||
parameter integer INMODEREG = 1;
|
||||
parameter integer MREG = 1;
|
||||
parameter integer OPMODEREG = 1;
|
||||
parameter integer PREG = 1;
|
||||
parameter SEL_MASK = "MASK";
|
||||
parameter SEL_PATTERN = "PATTERN";
|
||||
parameter USE_DPORT = "FALSE";
|
||||
parameter USE_MULT = "MULTIPLY";
|
||||
parameter USE_PATTERN_DETECT = "NO_PATDET";
|
||||
parameter USE_SIMD = "ONE48";
|
||||
parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
|
||||
parameter [47:0] PATTERN = 48'h000000000000;
|
||||
parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
|
||||
parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_CLK_INVERTED = 1'b0;
|
||||
parameter [4:0] IS_INMODE_INVERTED = 5'b0;
|
||||
parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
|
||||
|
||||
wire [47:0] $P, $PCOUT;
|
||||
|
||||
DSP48E1 #(
|
||||
.ACASCREG(ACASCREG),
|
||||
.ADREG(ADREG),
|
||||
.ALUMODEREG(ALUMODEREG),
|
||||
.AREG(AREG),
|
||||
.AUTORESET_PATDET(AUTORESET_PATDET),
|
||||
.A_INPUT(A_INPUT),
|
||||
.BCASCREG(BCASCREG),
|
||||
.BREG(BREG),
|
||||
.B_INPUT(B_INPUT),
|
||||
.CARRYINREG(CARRYINREG),
|
||||
.CARRYINSELREG(CARRYINSELREG),
|
||||
.CREG(CREG),
|
||||
.DREG(DREG),
|
||||
.INMODEREG(INMODEREG),
|
||||
.MREG(MREG),
|
||||
.OPMODEREG(OPMODEREG),
|
||||
.PREG(PREG),
|
||||
.SEL_MASK(SEL_MASK),
|
||||
.SEL_PATTERN(SEL_PATTERN),
|
||||
.USE_DPORT(USE_DPORT),
|
||||
.USE_MULT(USE_MULT),
|
||||
.USE_PATTERN_DETECT(USE_PATTERN_DETECT),
|
||||
.USE_SIMD(USE_SIMD),
|
||||
.MASK(MASK),
|
||||
.PATTERN(PATTERN),
|
||||
.IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED),
|
||||
.IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED),
|
||||
.IS_CLK_INVERTED(IS_CLK_INVERTED),
|
||||
.IS_INMODE_INVERTED(IS_INMODE_INVERTED),
|
||||
.IS_OPMODE_INVERTED(IS_OPMODE_INVERTED)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.ACOUT(ACOUT),
|
||||
.BCOUT(BCOUT),
|
||||
.CARRYCASCOUT(CARRYCASCOUT),
|
||||
.CARRYOUT(CARRYOUT),
|
||||
.MULTSIGNOUT(MULTSIGNOUT),
|
||||
.OVERFLOW(OVERFLOW),
|
||||
.P($P),
|
||||
.PATTERNBDETECT(PATTERNBDETECT),
|
||||
.PATTERNDETECT(PATTERNDETECT),
|
||||
.PCOUT($PCOUT),
|
||||
.UNDERFLOW(UNDERFLOW),
|
||||
.A(A),
|
||||
.ACIN(ACIN),
|
||||
.ALUMODE(ALUMODE),
|
||||
.B(B),
|
||||
.BCIN(BCIN),
|
||||
.C(C),
|
||||
.CARRYCASCIN(CARRYCASCIN),
|
||||
.CARRYIN(CARRYIN),
|
||||
.CARRYINSEL(CARRYINSEL),
|
||||
.CEA1(CEA1),
|
||||
.CEA2(CEA2),
|
||||
.CEAD(CEAD),
|
||||
.CEALUMODE(CEALUMODE),
|
||||
.CEB1(CEB1),
|
||||
.CEB2(CEB2),
|
||||
.CEC(CEC),
|
||||
.CECARRYIN(CECARRYIN),
|
||||
.CECTRL(CECTRL),
|
||||
.CED(CED),
|
||||
.CEINMODE(CEINMODE),
|
||||
.CEM(CEM),
|
||||
.CEP(CEP),
|
||||
.CLK(CLK),
|
||||
.D(D),
|
||||
.INMODE(INMODE),
|
||||
.MULTSIGNIN(MULTSIGNIN),
|
||||
.OPMODE(OPMODE),
|
||||
.PCIN(PCIN),
|
||||
.RSTA(RSTA),
|
||||
.RSTALLCARRYIN(RSTALLCARRYIN),
|
||||
.RSTALUMODE(RSTALUMODE),
|
||||
.RSTB(RSTB),
|
||||
.RSTC(RSTC),
|
||||
.RSTCTRL(RSTCTRL),
|
||||
.RSTD(RSTD),
|
||||
.RSTINMODE(RSTINMODE),
|
||||
.RSTM(RSTM),
|
||||
.RSTP(RSTP)
|
||||
);
|
||||
$__ABC9_DSP48E1 #(
|
||||
.ADREG(ADREG),
|
||||
.AREG(AREG),
|
||||
.BREG(BREG),
|
||||
.CREG(CREG),
|
||||
.DREG(DREG),
|
||||
.MREG(MREG),
|
||||
.PREG(PREG),
|
||||
.USE_DPORT(USE_DPORT),
|
||||
.USE_MULT(USE_MULT)
|
||||
) dsp_comb (
|
||||
.$A(A), .$B(B), .$C(C), .$D(D), .$P($P), .$PCIN(PCIN), .$PCOUT($PCOUT), .P(P), .PCOUT(PCOUT));
|
||||
endmodule
|
|
@ -37,174 +37,3 @@ module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1);
|
|||
(S1 => O) = 273;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
// Box to emulate async behaviour of FDC*
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module \$__ABC9_ASYNC0 (input A, S, output Y);
|
||||
assign Y = S ? 1'b0 : A;
|
||||
specify
|
||||
(A => Y) = 0;
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270
|
||||
(S => Y) = 764;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
// Box to emulate async behaviour of FDP*
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module \$__ABC9_ASYNC1 (input A, S, output Y);
|
||||
assign Y = S ? 1'b1 : A;
|
||||
specify
|
||||
(A => Y) = 0;
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270
|
||||
(S => Y) = 764;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
// Box to emulate comb/seq behaviour of RAM{32,64} and SRL{16,32}
|
||||
// Necessary since RAMD* and SRL* have both combinatorial (i.e.
|
||||
// same-cycle read operation) and sequential (write operation
|
||||
// is only committed on the next clock edge).
|
||||
// To model the combinatorial path, such cells have to be split
|
||||
// into comb and seq parts, with this box modelling only the former.
|
||||
(* abc9_box *)
|
||||
module \$__ABC9_RAM6 (input A, input [5:0] S, output Y);
|
||||
specify
|
||||
(A => Y) = 0;
|
||||
(S[0] => Y) = 642;
|
||||
(S[1] => Y) = 631;
|
||||
(S[2] => Y) = 472;
|
||||
(S[3] => Y) = 407;
|
||||
(S[4] => Y) = 238;
|
||||
(S[5] => Y) = 127;
|
||||
endspecify
|
||||
endmodule
|
||||
// Box to emulate comb/seq behaviour of RAM128
|
||||
(* abc9_box *)
|
||||
module \$__ABC9_RAM7 (input A, input [6:0] S, output Y);
|
||||
specify
|
||||
(A => Y) = 0;
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/1c85daf1b115da4d27ca83c6b89f53a94de39748/artix7/timings/slicel.sdf#L867
|
||||
(S[0] => Y) = 642 + 223 /* to cross F7BMUX */ + 174 /* CMUX */;
|
||||
(S[1] => Y) = 631 + 223 /* to cross F7BMUX */ + 174 /* CMUX */;
|
||||
(S[2] => Y) = 472 + 223 /* to cross F7BMUX */ + 174 /* CMUX */;
|
||||
(S[3] => Y) = 407 + 223 /* to cross F7BMUX */ + 174 /* CMUX */;
|
||||
(S[4] => Y) = 238 + 223 /* to cross F7BMUX */ + 174 /* CMUX */;
|
||||
(S[5] => Y) = 127 + 223 /* to cross F7BMUX */ + 174 /* CMUX */;
|
||||
(S[6] => Y) = 0 + 296 /* to select F7BMUX */ + 174 /* CMUX */;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
// Boxes used to represent the comb behaviour of DSP48E1
|
||||
(* abc9_box *)
|
||||
module $__ABC9_DSP48E1 (
|
||||
input [29:0] $A,
|
||||
input [17:0] $B,
|
||||
input [47:0] $C,
|
||||
input [24:0] $D,
|
||||
input [47:0] $P,
|
||||
input [47:0] $PCIN,
|
||||
input [47:0] $PCOUT,
|
||||
output [47:0] P,
|
||||
output [47:0] PCOUT
|
||||
);
|
||||
parameter integer ADREG = 1;
|
||||
parameter integer AREG = 1;
|
||||
parameter integer BREG = 1;
|
||||
parameter integer CREG = 1;
|
||||
parameter integer DREG = 1;
|
||||
parameter integer MREG = 1;
|
||||
parameter integer PREG = 1;
|
||||
parameter USE_DPORT = "FALSE";
|
||||
parameter USE_MULT = "MULTIPLY";
|
||||
|
||||
function integer \A.P.comb ;
|
||||
begin
|
||||
if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \A.P.comb = 2823;
|
||||
else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \A.P.comb = 3806;
|
||||
else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \A.P.comb = 1523;
|
||||
end
|
||||
endfunction
|
||||
function integer \A.PCOUT.comb ;
|
||||
begin
|
||||
if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \A.PCOUT.comb = 2970;
|
||||
else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \A.PCOUT.comb = 3954;
|
||||
else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \A.PCOUT.comb = 1671;
|
||||
end
|
||||
endfunction
|
||||
function integer \B.P.comb ;
|
||||
begin
|
||||
if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \B.P.comb = 2690;
|
||||
else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \B.P.comb = 2690;
|
||||
else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \B.P.comb = 1509;
|
||||
end
|
||||
endfunction
|
||||
function integer \B.PCOUT.comb ;
|
||||
begin
|
||||
if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \B.PCOUT.comb = 2838;
|
||||
else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \B.PCOUT.comb = 2838;
|
||||
else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \B.PCOUT.comb = 1658;
|
||||
end
|
||||
endfunction
|
||||
function integer \C.P.comb ;
|
||||
begin
|
||||
if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \C.P.comb = 1325;
|
||||
else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \C.P.comb = 1325;
|
||||
else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \C.P.comb = 1325;
|
||||
end
|
||||
endfunction
|
||||
function integer \C.PCOUT.comb ;
|
||||
begin
|
||||
if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \C.PCOUT.comb = 1474;
|
||||
else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \C.PCOUT.comb = 1474;
|
||||
else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \C.PCOUT.comb = 1474;
|
||||
end
|
||||
endfunction
|
||||
function integer \D.P.comb ;
|
||||
begin
|
||||
if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \D.P.comb = 3717;
|
||||
end
|
||||
endfunction
|
||||
function integer \D.PCOUT.comb ;
|
||||
begin
|
||||
if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \D.PCOUT.comb = 3700;
|
||||
end
|
||||
endfunction
|
||||
|
||||
specify
|
||||
($P *> P) = 0;
|
||||
($PCOUT *> PCOUT) = 0;
|
||||
endspecify
|
||||
|
||||
// Identical comb delays to DSP48E1 in cells_sim.v
|
||||
generate
|
||||
if (PREG == 0 && MREG == 0 && AREG == 0 && ADREG == 0)
|
||||
specify
|
||||
($A *> P) = \A.P.comb ();
|
||||
($A *> PCOUT) = \A.PCOUT.comb ();
|
||||
endspecify
|
||||
|
||||
if (PREG == 0 && MREG == 0 && BREG == 0)
|
||||
specify
|
||||
($B *> P) = \B.P.comb ();
|
||||
($B *> PCOUT) = \B.PCOUT.comb ();
|
||||
endspecify
|
||||
|
||||
if (PREG == 0 && CREG == 0)
|
||||
specify
|
||||
($C *> P) = \C.P.comb ();
|
||||
($C *> PCOUT) = \C.PCOUT.comb ();
|
||||
endspecify
|
||||
|
||||
if (PREG == 0 && MREG == 0 && ADREG == 0 && DREG == 0)
|
||||
specify
|
||||
($D *> P) = \D.P.comb ();
|
||||
($D *> PCOUT) = \D.PCOUT.comb ();
|
||||
endspecify
|
||||
|
||||
if (PREG == 0)
|
||||
specify
|
||||
($PCIN *> P) = 1107;
|
||||
($PCIN *> PCOUT) = 1255;
|
||||
endspecify
|
||||
endgenerate
|
||||
endmodule
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
|
||||
(* techmap_celltype = "$__ABC9_ASYNC0 $__ABC9_ASYNC1" *)
|
||||
module $__ABC9_ASYNC01(input A, S, output Y);
|
||||
assign Y = A;
|
||||
endmodule
|
||||
|
||||
module $__ABC9_FF_(input D, output Q);
|
||||
assign Q = D;
|
||||
endmodule
|
||||
|
||||
module $__ABC9_RAM6(input A, input [5:0] S, output Y);
|
||||
assign Y = A;
|
||||
endmodule
|
||||
module $__ABC9_RAM7(input A, input [6:0] S, output Y);
|
||||
assign Y = A;
|
||||
endmodule
|
||||
|
||||
module $__ABC9_DSP48E1(
|
||||
input [29:0] $A,
|
||||
input [17:0] $B,
|
||||
input [47:0] $C,
|
||||
input [24:0] $D,
|
||||
input [47:0] $P,
|
||||
input [47:0] $PCIN,
|
||||
input [47:0] $PCOUT,
|
||||
output [47:0] P,
|
||||
output [47:0] PCOUT
|
||||
);
|
||||
parameter integer ADREG = 1;
|
||||
parameter integer AREG = 1;
|
||||
parameter integer BREG = 1;
|
||||
parameter integer CREG = 1;
|
||||
parameter integer DREG = 1;
|
||||
parameter integer MREG = 1;
|
||||
parameter integer PREG = 1;
|
||||
parameter USE_DPORT = "FALSE";
|
||||
parameter USE_MULT = "MULTIPLY";
|
||||
|
||||
assign P = $P, PCOUT = $PCOUT;
|
||||
endmodule
|
|
@ -36,6 +36,9 @@ module IBUF(
|
|||
parameter IOSTANDARD = "default";
|
||||
parameter IBUF_LOW_PWR = 0;
|
||||
assign O = I;
|
||||
specify
|
||||
(I => O) = 0;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
module IBUFG(
|
||||
|
@ -57,6 +60,9 @@ module OBUF(
|
|||
parameter DRIVE = 12;
|
||||
parameter SLEW = "SLOW";
|
||||
assign O = I;
|
||||
specify
|
||||
(I => O) = 0;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
module IOBUF (
|
||||
|
@ -72,6 +78,10 @@ module IOBUF (
|
|||
parameter SLEW = "SLOW";
|
||||
assign IO = T ? 1'bz : I;
|
||||
assign O = IO;
|
||||
specify
|
||||
(I => IO) = 0;
|
||||
(IO => O) = 0;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
module OBUFT (
|
||||
|
@ -85,14 +95,20 @@ module OBUFT (
|
|||
parameter IOSTANDARD = "DEFAULT";
|
||||
parameter SLEW = "SLOW";
|
||||
assign O = T ? 1'bz : I;
|
||||
specify
|
||||
(I => O) = 0;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
module BUFG(
|
||||
(* clkbuf_driver *)
|
||||
output O,
|
||||
input I);
|
||||
|
||||
assign O = I;
|
||||
specify
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/CLK_BUFG_TOP_R.sdf#L11
|
||||
(I => O) = 96;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
module BUFGCTRL(
|
||||
|
@ -499,8 +515,8 @@ module FDRE (
|
|||
endgenerate
|
||||
specify
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249
|
||||
//$setup(D , posedge C &&& CE && !IS_C_INVERTED , -46); // Negative times not currently supported
|
||||
//$setup(D , negedge C &&& CE && IS_C_INVERTED , -46); // Negative times not currently supported
|
||||
$setup(D , posedge C &&& CE && !IS_C_INVERTED , /*-46*/ 0); // Negative times not currently supported
|
||||
$setup(D , negedge C &&& CE && IS_C_INVERTED , /*-46*/ 0); // Negative times not currently supported
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248
|
||||
$setup(CE, posedge C &&& !IS_C_INVERTED, 109);
|
||||
$setup(CE, negedge C &&& IS_C_INVERTED, 109);
|
||||
|
@ -508,10 +524,10 @@ module FDRE (
|
|||
$setup(R , posedge C &&& !IS_C_INVERTED, 404);
|
||||
$setup(R , negedge C &&& IS_C_INVERTED, 404);
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L243
|
||||
if (!IS_C_INVERTED && R ^ IS_R_INVERTED) (posedge C => (Q : 1'b0)) = 303;
|
||||
if ( IS_C_INVERTED && R ^ IS_R_INVERTED) (negedge C => (Q : 1'b0)) = 303;
|
||||
if (!IS_C_INVERTED && R ~^ IS_R_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
if ( IS_C_INVERTED && R ~^ IS_R_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
if (!IS_C_INVERTED && R != IS_R_INVERTED) (posedge C => (Q : 1'b0)) = 303;
|
||||
if ( IS_C_INVERTED && R != IS_R_INVERTED) (negedge C => (Q : 1'b0)) = 303;
|
||||
if (!IS_C_INVERTED && R == IS_R_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
if ( IS_C_INVERTED && R == IS_R_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
|
@ -529,7 +545,7 @@ module FDRE_1 (
|
|||
always @(negedge C) if (R) Q <= 1'b0; else if (CE) Q <= D;
|
||||
specify
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249
|
||||
//$setup(D , negedge C &&& CE, -46); // Negative times not currently supported
|
||||
$setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248
|
||||
$setup(CE, negedge C, 109);
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274
|
||||
|
@ -564,8 +580,8 @@ module FDSE (
|
|||
endgenerate
|
||||
specify
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249
|
||||
//$setup(D , posedge C &&& !IS_C_INVERTED && CE, -46); // Negative times not currently supported
|
||||
//$setup(D , negedge C &&& IS_C_INVERTED && CE, -46); // Negative times not currently supported
|
||||
$setup(D , posedge C &&& !IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported
|
||||
$setup(D , negedge C &&& IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248
|
||||
$setup(CE, posedge C &&& !IS_C_INVERTED, 109);
|
||||
$setup(CE, negedge C &&& IS_C_INVERTED, 109);
|
||||
|
@ -573,10 +589,10 @@ module FDSE (
|
|||
$setup(S , posedge C &&& !IS_C_INVERTED, 404);
|
||||
$setup(S , negedge C &&& IS_C_INVERTED, 404);
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L243
|
||||
if (!IS_C_INVERTED && S ^ IS_S_INVERTED) (posedge C => (Q : 1'b1)) = 303;
|
||||
if ( IS_C_INVERTED && S ^ IS_S_INVERTED) (negedge C => (Q : 1'b1)) = 303;
|
||||
if (!IS_C_INVERTED && S ~^ IS_S_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
if ( IS_C_INVERTED && S ~^ IS_S_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
if (!IS_C_INVERTED && S != IS_S_INVERTED) (posedge C => (Q : 1'b1)) = 303;
|
||||
if ( IS_C_INVERTED && S != IS_S_INVERTED) (negedge C => (Q : 1'b1)) = 303;
|
||||
if (!IS_C_INVERTED && S == IS_S_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
if ( IS_C_INVERTED && S == IS_S_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
|
@ -594,7 +610,7 @@ module FDSE_1 (
|
|||
always @(negedge C) if (S) Q <= 1'b1; else if (CE) Q <= D;
|
||||
specify
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249
|
||||
//$setup(D , negedge C &&& CE, -46); // Negative times not currently supported
|
||||
$setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248
|
||||
$setup(CE, negedge C, 109);
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274
|
||||
|
@ -640,7 +656,7 @@ module FDRSE (
|
|||
Q <= d;
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module FDCE (
|
||||
output reg Q,
|
||||
(* clkbuf_sink *)
|
||||
|
@ -667,8 +683,8 @@ module FDCE (
|
|||
endgenerate
|
||||
specify
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249
|
||||
//$setup(D , posedge C &&& !IS_C_INVERTED && CE, -46); // Negative times not currently supported
|
||||
//$setup(D , negedge C &&& IS_C_INVERTED && CE, -46); // Negative times not currently supported
|
||||
$setup(D , posedge C &&& !IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported
|
||||
$setup(D , negedge C &&& IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248
|
||||
$setup(CE , posedge C &&& !IS_C_INVERTED, 109);
|
||||
$setup(CE , negedge C &&& IS_C_INVERTED, 109);
|
||||
|
@ -676,14 +692,20 @@ module FDCE (
|
|||
$setup(CLR, posedge C &&& !IS_C_INVERTED, 404);
|
||||
$setup(CLR, negedge C &&& IS_C_INVERTED, 404);
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270
|
||||
//if (!IS_CLR_INVERTED) (posedge CLR => (Q : 1'b0)) = 764; // Captured by $__ABC9_ASYNC0
|
||||
//if ( IS_CLR_INVERTED) (negedge CLR => (Q : 1'b0)) = 764; // Captured by $__ABC9_ASYNC0
|
||||
if (!IS_C_INVERTED && CLR ~^ IS_CLR_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
if ( IS_C_INVERTED && CLR ~^ IS_CLR_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
`ifndef YOSYS
|
||||
if (!IS_CLR_INVERTED) (posedge CLR => (Q : 1'b0)) = 764;
|
||||
if ( IS_CLR_INVERTED) (negedge CLR => (Q : 1'b0)) = 764;
|
||||
`else
|
||||
if (IS_CLR_INVERTED != CLR) (CLR => Q) = 764; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
if (!IS_C_INVERTED && CLR == IS_CLR_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
if ( IS_C_INVERTED && CLR == IS_CLR_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module FDCE_1 (
|
||||
output reg Q,
|
||||
(* clkbuf_sink *)
|
||||
|
@ -697,18 +719,24 @@ module FDCE_1 (
|
|||
always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
|
||||
specify
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249
|
||||
//$setup(D , negedge C &&& CE, -46); // Negative times not currently supported
|
||||
$setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248
|
||||
$setup(CE , negedge C, 109);
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274
|
||||
$setup(CLR, negedge C, 404);
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270
|
||||
//(posedge CLR => (Q : 1'b0)) = 764; // Captured by $__ABC9_ASYNC0
|
||||
`ifndef YOSYS
|
||||
(posedge CLR => (Q : 1'b0)) = 764;
|
||||
`else
|
||||
if (CLR) (CLR => Q) = 764; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
if (!CLR && CE) (negedge C => (Q : D)) = 303;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module FDPE (
|
||||
output reg Q,
|
||||
(* clkbuf_sink *)
|
||||
|
@ -734,8 +762,8 @@ module FDPE (
|
|||
endgenerate
|
||||
specify
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249
|
||||
//$setup(D , posedge C &&& !IS_C_INVERTED && CE, -46); // Negative times not currently supported
|
||||
//$setup(D , negedge C &&& IS_C_INVERTED && CE, -46); // Negative times not currently supported
|
||||
$setup(D , posedge C &&& !IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported
|
||||
$setup(D , negedge C &&& IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248
|
||||
$setup(CE , posedge C &&& !IS_C_INVERTED, 109);
|
||||
$setup(CE , negedge C &&& IS_C_INVERTED, 109);
|
||||
|
@ -743,14 +771,20 @@ module FDPE (
|
|||
$setup(PRE, posedge C &&& !IS_C_INVERTED, 404);
|
||||
$setup(PRE, negedge C &&& IS_C_INVERTED, 404);
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270
|
||||
//if (!IS_PRE_INVERTED) (posedge PRE => (Q : 1'b1)) = 764; // Captured by $__ABC9_ASYNC1
|
||||
//if ( IS_PRE_INVERTED) (negedge PRE => (Q : 1'b1)) = 764; // Captured by $__ABC9_ASYNC1
|
||||
if (!IS_C_INVERTED && PRE ~^ IS_PRE_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
if ( IS_C_INVERTED && PRE ~^ IS_PRE_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
`ifndef YOSYS
|
||||
if (!IS_PRE_INVERTED) (posedge PRE => (Q : 1'b1)) = 764;
|
||||
if ( IS_PRE_INVERTED) (negedge PRE => (Q : 1'b1)) = 764;
|
||||
`else
|
||||
if (IS_PRE_INVERTED != PRE) (PRE => Q) = 764; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
if (!IS_C_INVERTED && PRE == IS_PRE_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
if ( IS_C_INVERTED && PRE == IS_PRE_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module FDPE_1 (
|
||||
output reg Q,
|
||||
(* clkbuf_sink *)
|
||||
|
@ -764,14 +798,19 @@ module FDPE_1 (
|
|||
always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
|
||||
specify
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249
|
||||
//$setup(D , negedge C &&& CE, -46); // Negative times not currently supported
|
||||
$setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248
|
||||
$setup(CE , negedge C, 109);
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274
|
||||
$setup(PRE, negedge C, 404);
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270
|
||||
//if (!IS_PRE_INVERTED) (posedge PRE => (Q : 1'b1)) = 764; // Captured by $__ABC9_ASYNC1
|
||||
//if (IS_PRE_INVERTED) (negedge PRE => (Q : 1'b1)) = 764; // Captured by $__ABC9_ASYNC1
|
||||
`ifndef YOSYS
|
||||
(posedge PRE => (Q : 1'b1)) = 764;
|
||||
`else
|
||||
if (PRE) (PRE => Q) = 764; // Technically, this should be an edge sensitive path
|
||||
// but for facilitating a bypass box, let's pretend it's
|
||||
// a simple path
|
||||
`endif
|
||||
if (!PRE && CE) (negedge C => (Q : D)) = 303;
|
||||
endspecify
|
||||
endmodule
|
||||
|
@ -1383,6 +1422,7 @@ module RAM16X1D_1 (
|
|||
always @(negedge clk) if (WE) mem[a] <= D;
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module RAM32X1D (
|
||||
output DPO, SPO,
|
||||
input D,
|
||||
|
@ -1429,15 +1469,15 @@ module RAM32X1D (
|
|||
if (!IS_WCLK_INVERTED) (posedge WCLK => (DPO : 1'bx)) = 1153;
|
||||
if ( IS_WCLK_INVERTED) (posedge WCLK => (SPO : D)) = 1153;
|
||||
if ( IS_WCLK_INVERTED) (negedge WCLK => (DPO : 1'bx)) = 1153;
|
||||
// Captured by $__ABC9_RAM6
|
||||
//({A0,DPRA0} => {SPO,DPO}) = 642;
|
||||
//({A1,DPRA1} => {SPO,DPO}) = 631;
|
||||
//({A2,DPRA2} => {SPO,DPO}) = 472;
|
||||
//({A3,DPRA3} => {SPO,DPO}) = 407;
|
||||
//({A4,DPRA4} => {SPO,DPO}) = 238;
|
||||
(A0 => SPO) = 642; (DPRA0 => DPO) = 642;
|
||||
(A1 => SPO) = 632; (DPRA1 => DPO) = 631;
|
||||
(A2 => SPO) = 472; (DPRA2 => DPO) = 472;
|
||||
(A3 => SPO) = 407; (DPRA3 => DPO) = 407;
|
||||
(A4 => SPO) = 238; (DPRA4 => DPO) = 238;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module RAM32X1D_1 (
|
||||
output DPO, SPO,
|
||||
input D,
|
||||
|
@ -1479,15 +1519,15 @@ module RAM32X1D_1 (
|
|||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981
|
||||
if (WE) (negedge WCLK => (SPO : D)) = 1153;
|
||||
if (WE) (negedge WCLK => (DPO : 1'bx)) = 1153;
|
||||
// Captured by $__ABC9_RAM6
|
||||
//({A0,DPRA0} => {SPO,DPO}) = 642;
|
||||
//({A1,DPRA1} => {SPO,DPO}) = 631;
|
||||
//({A2,DPRA2} => {SPO,DPO}) = 472;
|
||||
//({A3,DPRA3} => {SPO,DPO}) = 407;
|
||||
//({A4,DPRA4} => {SPO,DPO}) = 238;
|
||||
(A0 => SPO) = 642; (DPRA0 => DPO) = 642;
|
||||
(A1 => SPO) = 632; (DPRA1 => DPO) = 631;
|
||||
(A2 => SPO) = 472; (DPRA2 => DPO) = 472;
|
||||
(A3 => SPO) = 407; (DPRA3 => DPO) = 407;
|
||||
(A4 => SPO) = 238; (DPRA4 => DPO) = 238;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module RAM64X1D (
|
||||
output DPO, SPO,
|
||||
input D,
|
||||
|
@ -1537,13 +1577,12 @@ module RAM64X1D (
|
|||
if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DPO : 1'bx)) = 1153;
|
||||
if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (SPO : D)) = 1153;
|
||||
if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DPO : 1'bx)) = 1153;
|
||||
// Captured by $__ABC9_RAM6
|
||||
//({A0,DPRA0} => {SPO,DPO}) = 642;
|
||||
//({A1,DPRA1} => {SPO,DPO}) = 631;
|
||||
//({A2,DPRA2} => {SPO,DPO}) = 472;
|
||||
//({A3,DPRA3} => {SPO,DPO}) = 407;
|
||||
//({A4,DPRA4} => {SPO,DPO}) = 238;
|
||||
//({A5,DPRA5} => {SPO,DPO}) = 127;
|
||||
(A0 => SPO) = 642; (DPRA0 => DPO) = 642;
|
||||
(A1 => SPO) = 632; (DPRA1 => DPO) = 631;
|
||||
(A2 => SPO) = 472; (DPRA2 => DPO) = 472;
|
||||
(A3 => SPO) = 407; (DPRA3 => DPO) = 407;
|
||||
(A4 => SPO) = 238; (DPRA4 => DPO) = 238;
|
||||
(A5 => SPO) = 127; (DPRA5 => DPO) = 127;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
|
@ -1586,9 +1625,16 @@ module RAM64X1D_1 (
|
|||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981
|
||||
if (WE) (negedge WCLK => (SPO : D)) = 1153;
|
||||
if (WE) (negedge WCLK => (DPO : 1'bx)) = 1153;
|
||||
(A0 => SPO) = 642; (DPRA0 => DPO) = 642;
|
||||
(A1 => SPO) = 632; (DPRA1 => DPO) = 631;
|
||||
(A2 => SPO) = 472; (DPRA2 => DPO) = 472;
|
||||
(A3 => SPO) = 407; (DPRA3 => DPO) = 407;
|
||||
(A4 => SPO) = 238; (DPRA4 => DPO) = 238;
|
||||
(A5 => SPO) = 127; (DPRA5 => DPO) = 127;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module RAM128X1D (
|
||||
output DPO, SPO,
|
||||
input D,
|
||||
|
@ -1632,22 +1678,21 @@ module RAM128X1D (
|
|||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981
|
||||
if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (SPO : D)) = 1153 + 217 /* to cross F7AMUX */ + 175 /* AMUX */;
|
||||
if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DPO : 1'bx)) = 1153 + 223 /* to cross F7BMUX */ + 174 /* CMUX */;
|
||||
(A[0] => SPO) = 642 + 193 /* to cross F7AMUX */ + 175 /* AMUX */;
|
||||
(A[1] => SPO) = 631 + 193 /* to cross F7AMUX */ + 175 /* AMUX */;
|
||||
(A[2] => SPO) = 472 + 193 /* to cross F7AMUX */ + 175 /* AMUX */;
|
||||
(A[3] => SPO) = 407 + 193 /* to cross F7AMUX */ + 175 /* AMUX */;
|
||||
(A[4] => SPO) = 238 + 193 /* to cross F7AMUX */ + 175 /* AMUX */;
|
||||
(A[5] => SPO) = 127 + 193 /* to cross F7AMUX */ + 175 /* AMUX */;
|
||||
(A[6] => SPO) = 0 + 276 /* to select F7AMUX */ + 175 /* AMUX */;
|
||||
(DPRA[0] => DPO) = 642 + 223 /* to cross MUXF7 */ + 174 /* CMUX */;
|
||||
(DPRA[1] => DPO) = 631 + 223 /* to cross MUXF7 */ + 174 /* CMUX */;
|
||||
(DPRA[2] => DPO) = 472 + 223 /* to cross MUXF7 */ + 174 /* CMUX */;
|
||||
(DPRA[3] => DPO) = 407 + 223 /* to cross MUXF7 */ + 174 /* CMUX */;
|
||||
(DPRA[4] => DPO) = 238 + 223 /* to cross MUXF7 */ + 174 /* CMUX */;
|
||||
(DPRA[5] => DPO) = 127 + 223 /* to cross MUXF7 */ + 174 /* CMUX */;
|
||||
(DPRA[6] => DPO) = 0 + 296 /* to select MUXF7 */ + 174 /* CMUX */;
|
||||
`endif
|
||||
// Captured by $__ABC9_RAM7
|
||||
//(A[0] => SPO) = 642 + 193 /* to cross F7AMUX */ + 175 /* AMUX */;
|
||||
//(A[1] => SPO) = 631 + 193 /* to cross F7AMUX */ + 175 /* AMUX */;
|
||||
//(A[2] => SPO) = 472 + 193 /* to cross F7AMUX */ + 175 /* AMUX */;
|
||||
//(A[3] => SPO) = 407 + 193 /* to cross F7AMUX */ + 175 /* AMUX */;
|
||||
//(A[4] => SPO) = 238 + 193 /* to cross F7AMUX */ + 175 /* AMUX */;
|
||||
//(A[5] => SPO) = 127 + 193 /* to cross F7AMUX */ + 175 /* AMUX */;
|
||||
//(A[6] => SPO) = 0 + 276 /* to select F7AMUX */ + 175 /* AMUX */;
|
||||
//(DPRA[0] => DPO) = 642 + 223 /* to cross MUXF7 */ + 174 /* CMUX */;
|
||||
//(DPRA[1] => DPO) = 631 + 223 /* to cross MUXF7 */ + 174 /* CMUX */;
|
||||
//(DPRA[2] => DPO) = 472 + 223 /* to cross MUXF7 */ + 174 /* CMUX */;
|
||||
//(DPRA[3] => DPO) = 407 + 223 /* to cross MUXF7 */ + 174 /* CMUX */;
|
||||
//(DPRA[4] => DPO) = 238 + 223 /* to cross MUXF7 */ + 174 /* CMUX */;
|
||||
//(DPRA[5] => DPO) = 127 + 223 /* to cross MUXF7 */ + 174 /* CMUX */;
|
||||
//(DPRA[6] => DPO) = 0 + 296 /* to select MUXF7 */ + 174 /* CMUX */;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
|
@ -1671,6 +1716,7 @@ endmodule
|
|||
|
||||
// Multi port.
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module RAM32M (
|
||||
output [1:0] DOA,
|
||||
output [1:0] DOB,
|
||||
|
@ -1767,12 +1813,11 @@ module RAM32M (
|
|||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1061
|
||||
if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOD[1] : DID[1])) = 1190;
|
||||
if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOD[1] : DID[1])) = 1190;
|
||||
// Captured by $__ABC9_RAM6
|
||||
//({{2{ADDRA[0]}},{2{ADDRB[0]}},{2{ADDRC[0]}},{2{ADDRD[0]}}} => {DOA,DOB,DOC,DOD}) = 642;
|
||||
//({{2{ADDRA[1]}},{2{ADDRB[1]}},{2{ADDRC[1]}},{2{ADDRD[1]}}} => {DOA,DOB,DOC,DOD}) = 631;
|
||||
//({{2{ADDRA[2]}},{2{ADDRB[2]}},{2{ADDRC[2]}},{2{ADDRD[2]}}} => {DOA,DOB,DOC,DOD}) = 472;
|
||||
//({{2{ADDRA[3]}},{2{ADDRB[3]}},{2{ADDRC[3]}},{2{ADDRD[3]}}} => {DOA,DOB,DOC,DOD}) = 407;
|
||||
//({{2{ADDRA[4]}},{2{ADDRB[4]}},{2{ADDRC[4]}},{2{ADDRD[4]}}} => {DOA,DOB,DOC,DOD}) = 238;
|
||||
(ADDRA[0] *> DOA) = 642; (ADDRB[0] *> DOB) = 642; (ADDRC[0] *> DOC) = 642; (ADDRD[0] *> DOD) = 642;
|
||||
(ADDRA[1] *> DOA) = 631; (ADDRB[1] *> DOB) = 631; (ADDRC[1] *> DOC) = 631; (ADDRD[1] *> DOD) = 631;
|
||||
(ADDRA[2] *> DOA) = 472; (ADDRB[2] *> DOB) = 472; (ADDRC[2] *> DOC) = 472; (ADDRD[2] *> DOD) = 472;
|
||||
(ADDRA[3] *> DOA) = 407; (ADDRB[3] *> DOB) = 407; (ADDRC[3] *> DOC) = 407; (ADDRD[3] *> DOD) = 407;
|
||||
(ADDRA[4] *> DOA) = 238; (ADDRB[4] *> DOB) = 238; (ADDRC[4] *> DOC) = 238; (ADDRD[4] *> DOD) = 238;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
|
@ -1845,6 +1890,7 @@ module RAM32M16 (
|
|||
end
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module RAM64M (
|
||||
output DOA,
|
||||
output DOB,
|
||||
|
@ -1923,12 +1969,11 @@ module RAM64M (
|
|||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1093
|
||||
if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOD : DID)) = 1163;
|
||||
if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOD : DID)) = 1163;
|
||||
// Captured by $__ABC9_RAM6
|
||||
//({ADDRA[0],ADDRB[0],ADDRC[0],ADDRD[0]} => {DOA,DOB,DOC,DOD}) = 642;
|
||||
//({ADDRA[1],ADDRB[1],ADDRC[1],ADDRD[1]} => {DOA,DOB,DOC,DOD}) = 631;
|
||||
//({ADDRA[2],ADDRB[2],ADDRC[2],ADDRD[2]} => {DOA,DOB,DOC,DOD}) = 472;
|
||||
//({ADDRA[3],ADDRB[3],ADDRC[3],ADDRD[3]} => {DOA,DOB,DOC,DOD}) = 407;
|
||||
//({ADDRA[4],ADDRB[4],ADDRC[4],ADDRD[4]} => {DOA,DOB,DOC,DOD}) = 238;
|
||||
(ADDRA[0] => DOA) = 642; (ADDRB[0] => DOB) = 642; (ADDRC[0] => DOC) = 642; (ADDRD[0] => DOD) = 642;
|
||||
(ADDRA[1] => DOA) = 631; (ADDRB[1] => DOB) = 631; (ADDRC[1] => DOC) = 631; (ADDRD[1] => DOD) = 631;
|
||||
(ADDRA[2] => DOA) = 472; (ADDRB[2] => DOB) = 472; (ADDRC[2] => DOC) = 472; (ADDRD[2] => DOD) = 472;
|
||||
(ADDRA[3] => DOA) = 407; (ADDRB[3] => DOB) = 407; (ADDRC[3] => DOC) = 407; (ADDRD[3] => DOD) = 407;
|
||||
(ADDRA[4] => DOA) = 238; (ADDRB[4] => DOB) = 238; (ADDRC[4] => DOC) = 238; (ADDRD[4] => DOD) = 238;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
|
@ -2045,6 +2090,7 @@ endmodule
|
|||
|
||||
// Shift registers.
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module SRL16 (
|
||||
output Q,
|
||||
input A0, A1, A2, A3,
|
||||
|
@ -2063,14 +2109,14 @@ module SRL16 (
|
|||
(posedge CLK => (Q : 1'bx)) = 1472;
|
||||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912
|
||||
$setup(D , posedge CLK, 173);
|
||||
// Captured by $__ABC9_RAM6
|
||||
//(A0 => Q) = 631;
|
||||
//(A1 => Q) = 472;
|
||||
//(A2 => Q) = 407;
|
||||
//(A3 => Q) = 238;
|
||||
(A0 => Q) = 631;
|
||||
(A1 => Q) = 472;
|
||||
(A2 => Q) = 407;
|
||||
(A3 => Q) = 238;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module SRL16E (
|
||||
output Q,
|
||||
input A0, A1, A2, A3, CE,
|
||||
|
@ -2096,16 +2142,19 @@ module SRL16E (
|
|||
$setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173);
|
||||
$setup(D , negedge CLK &&& IS_CLK_INVERTED, 173);
|
||||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905
|
||||
if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : D)) = 1472;
|
||||
if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : D)) = 1472;
|
||||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905
|
||||
if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : 1'bx)) = 1472;
|
||||
if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : 1'bx)) = 1472;
|
||||
// Captured by $__ABC9_RAM6
|
||||
//(A0 => Q) = 631;
|
||||
//(A1 => Q) = 472;
|
||||
//(A2 => Q) = 407;
|
||||
//(A3 => Q) = 238;
|
||||
(A0 => Q) = 631;
|
||||
(A1 => Q) = 472;
|
||||
(A2 => Q) = 407;
|
||||
(A3 => Q) = 238;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module SRLC16 (
|
||||
output Q,
|
||||
output Q15,
|
||||
|
@ -2122,18 +2171,20 @@ module SRLC16 (
|
|||
always @(posedge CLK) r <= { r[14:0], D };
|
||||
|
||||
specify
|
||||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905
|
||||
(posedge CLK => (Q : 1'bx)) = 1472;
|
||||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912
|
||||
$setup(D , posedge CLK, 173);
|
||||
// Captured by $__ABC9_RAM6
|
||||
//(A0 => Q) = 631;
|
||||
//(A1 => Q) = 472;
|
||||
//(A2 => Q) = 407;
|
||||
//(A3 => Q) = 238;
|
||||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905
|
||||
(posedge CLK => (Q : 1'bx)) = 1472;
|
||||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904
|
||||
(posedge CLK => (Q15 : 1'bx)) = 1114;
|
||||
(A0 => Q) = 631;
|
||||
(A1 => Q) = 472;
|
||||
(A2 => Q) = 407;
|
||||
(A3 => Q) = 238;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module SRLC16E (
|
||||
output Q,
|
||||
output Q15,
|
||||
|
@ -2160,18 +2211,23 @@ module SRLC16E (
|
|||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912
|
||||
$setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173);
|
||||
$setup(D , negedge CLK &&& IS_CLK_INVERTED, 173);
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248
|
||||
$setup(CE, posedge CLK &&& !IS_CLK_INVERTED, 109);
|
||||
$setup(CE, negedge CLK &&& IS_CLK_INVERTED, 109);
|
||||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905
|
||||
if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : D)) = 1472;
|
||||
if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : D)) = 1472;
|
||||
// Captured by $__ABC9_RAM6
|
||||
//(A0 => Q) = 642;
|
||||
//(A1 => Q) = 631;
|
||||
//(A2 => Q) = 472;
|
||||
//(A3 => Q) = 407;
|
||||
//(A4 => Q) = 238;
|
||||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904
|
||||
if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q15 : 1'bx)) = 1114;
|
||||
if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q15 : 1'bx)) = 1114;
|
||||
(A0 => Q) = 631;
|
||||
(A1 => Q) = 472;
|
||||
(A2 => Q) = 407;
|
||||
(A3 => Q) = 238;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module SRLC32E (
|
||||
output Q,
|
||||
output Q31,
|
||||
|
@ -2199,18 +2255,20 @@ module SRLC32E (
|
|||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912
|
||||
$setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173);
|
||||
$setup(D , negedge CLK &&& IS_CLK_INVERTED, 173);
|
||||
// https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248
|
||||
$setup(CE, posedge CLK &&& !IS_CLK_INVERTED, 109);
|
||||
$setup(CE, negedge CLK &&& IS_CLK_INVERTED, 109);
|
||||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905
|
||||
if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : 1'bx)) = 1472;
|
||||
if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : 1'bx)) = 1472;
|
||||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904
|
||||
if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : 1'bx)) = 1114;
|
||||
if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : 1'bx)) = 1114;
|
||||
// Captured by $__ABC9_RAM6
|
||||
//(A0 => Q) = 642;
|
||||
//(A1 => Q) = 631;
|
||||
//(A2 => Q) = 472;
|
||||
//(A3 => Q) = 407;
|
||||
//(A4 => Q) = 238;
|
||||
if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q31 : 1'bx)) = 1114;
|
||||
if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q31 : 1'bx)) = 1114;
|
||||
(A[0] => Q) = 642;
|
||||
(A[1] => Q) = 631;
|
||||
(A[2] => Q) = 472;
|
||||
(A[3] => Q) = 407;
|
||||
(A[4] => Q) = 238;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
|
@ -2978,6 +3036,10 @@ endmodule
|
|||
|
||||
// Virtex 6, Series 7.
|
||||
|
||||
`ifdef YOSYS
|
||||
(* abc9_box=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG),
|
||||
lib_whitebox=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG) *)
|
||||
`endif
|
||||
module DSP48E1 (
|
||||
output [29:0] ACOUT,
|
||||
output [17:0] BCOUT,
|
||||
|
|
|
@ -143,7 +143,7 @@ struct SynthXilinxPass : public ScriptPass
|
|||
|
||||
std::string top_opt, edif_file, blif_file, family;
|
||||
bool flatten, retime, vpr, ise, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram;
|
||||
bool abc9, dff_mode;
|
||||
bool abc9, dff;
|
||||
bool flatten_before_abc;
|
||||
int widemux;
|
||||
int lut_size;
|
||||
|
@ -170,7 +170,7 @@ struct SynthXilinxPass : public ScriptPass
|
|||
nodsp = false;
|
||||
uram = false;
|
||||
abc9 = false;
|
||||
dff_mode = false;
|
||||
dff = false;
|
||||
flatten_before_abc = false;
|
||||
widemux = 0;
|
||||
lut_size = 6;
|
||||
|
@ -217,7 +217,7 @@ struct SynthXilinxPass : public ScriptPass
|
|||
continue;
|
||||
}
|
||||
if (args[argidx] == "-retime") {
|
||||
dff_mode = true;
|
||||
dff = true;
|
||||
retime = true;
|
||||
continue;
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ struct SynthXilinxPass : public ScriptPass
|
|||
continue;
|
||||
}
|
||||
if (args[argidx] == "-dff") {
|
||||
dff_mode = true;
|
||||
dff = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
@ -595,9 +595,11 @@ struct SynthXilinxPass : public ScriptPass
|
|||
run("clean");
|
||||
}
|
||||
|
||||
if (check_label("map_ffs")) {
|
||||
if (check_label("map_ffs", "('-abc9' only)")) {
|
||||
if (abc9 || help_mode) {
|
||||
run("techmap -map " + ff_map_file, "('-abc9' only)");
|
||||
if (dff || help_mode)
|
||||
run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "('-dff' only)");
|
||||
run("techmap -map " + ff_map_file);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -606,18 +608,14 @@ struct SynthXilinxPass : public ScriptPass
|
|||
if (flatten_before_abc)
|
||||
run("flatten");
|
||||
if (help_mode)
|
||||
run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for 'nowidelut', '-dff', '-retime')");
|
||||
run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for '-nowidelut', '-dff', '-retime')");
|
||||
else if (abc9) {
|
||||
if (lut_size != 6)
|
||||
log_error("'synth_xilinx -abc9' not currently supported for LUT4-based devices.\n");
|
||||
if (family != "xc7")
|
||||
log_warning("'synth_xilinx -abc9' not currently supported for the '%s' family, "
|
||||
"will use timing for 'xc7' instead.\n", family.c_str());
|
||||
std::string techmap_args = "-map +/xilinx/abc9_map.v -max_iter 1";
|
||||
if (dff_mode)
|
||||
techmap_args += " -D DFF_MODE";
|
||||
run("techmap " + techmap_args);
|
||||
run("read_verilog -icells -lib -specify +/abc9_model.v +/xilinx/abc9_model.v");
|
||||
run("read_verilog -icells -lib -specify +/xilinx/abc9_model.v");
|
||||
std::string abc9_opts;
|
||||
std::string k = "synth_xilinx.abc9.W";
|
||||
if (active_design && active_design->scratchpad.count(k))
|
||||
|
@ -628,10 +626,9 @@ struct SynthXilinxPass : public ScriptPass
|
|||
}
|
||||
if (nowidelut)
|
||||
abc9_opts += stringf(" -maxlut %d", lut_size);
|
||||
if (dff_mode)
|
||||
if (dff)
|
||||
abc9_opts += " -dff";
|
||||
run("abc9" + abc9_opts);
|
||||
run("techmap -map +/xilinx/abc9_unmap.v");
|
||||
}
|
||||
else {
|
||||
std::string abc_opts;
|
||||
|
@ -648,7 +645,7 @@ struct SynthXilinxPass : public ScriptPass
|
|||
else
|
||||
abc_opts += " -luts 2:2,3,6:5,10,20,40";
|
||||
}
|
||||
if (dff_mode)
|
||||
if (dff)
|
||||
abc_opts += " -dff";
|
||||
if (retime)
|
||||
abc_opts += " -D 1";
|
||||
|
|
|
@ -1,32 +1,85 @@
|
|||
logger -nowarn "Yosys has only limited support for tri-state logic at the moment\. .*"
|
||||
|
||||
read_verilog <<EOT
|
||||
module top(input C, D, output [7:0] Q);
|
||||
FDRE fd1(.C(C), .CE(1'b1), .D(D), .R(1'b1), .Q(Q[0]));
|
||||
FDSE fd2(.C(C), .CE(1'b1), .D(D), .S(1'b1), .Q(Q[1]));
|
||||
FDCE fd3(.C(C), .CE(1'b1), .D(D), .CLR(1'b1), .Q(Q[2]));
|
||||
FDPE fd4(.C(C), .CE(1'b1), .D(D), .PRE(1'b1), .Q(Q[3]));
|
||||
FDRE_1 fd5(.C(C), .CE(1'b1), .D(D), .R(1'b1), .Q(Q[4]));
|
||||
FDSE_1 fd6(.C(C), .CE(1'b1), .D(D), .S(1'b1), .Q(Q[5]));
|
||||
FDCE_1 fd7(.C(C), .CE(1'b1), .D(D), .CLR(1'b1), .Q(Q[6]));
|
||||
FDPE_1 fd8(.C(C), .CE(1'b1), .D(D), .PRE(1'b1), .Q(Q[7]));
|
||||
FDRE /*#(.INIT(0))*/ fd1(.C(C), .CE(1'b1), .D(D), .R(1'b1), .Q(Q[0]));
|
||||
FDSE #(.INIT(0)) fd2(.C(C), .CE(1'b1), .D(D), .S(1'b1), .Q(Q[1]));
|
||||
FDCE #(.INIT(0)) fd3(.C(C), .CE(1'b1), .D(D), .CLR(1'b1), .Q(Q[2]));
|
||||
FDPE #(.INIT(0)) fd4(.C(C), .CE(1'b1), .D(D), .PRE(1'b1), .Q(Q[3]));
|
||||
FDRE_1 #(.INIT(0)) fd5(.C(C), .CE(1'b1), .D(D), .R(1'b1), .Q(Q[4]));
|
||||
FDSE_1 #(.INIT(0)) fd6(.C(C), .CE(1'b1), .D(D), .S(1'b1), .Q(Q[5]));
|
||||
FDCE_1 #(.INIT(0)) fd7(.C(C), .CE(1'b1), .D(D), .CLR(1'b1), .Q(Q[6]));
|
||||
FDPE_1 #(.INIT(0)) fd8(.C(C), .CE(1'b1), .D(D), .PRE(1'b1), .Q(Q[7]));
|
||||
endmodule
|
||||
EOT
|
||||
equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf
|
||||
design -load postopt
|
||||
select -assert-none t:FD*
|
||||
select -assert-count 6 t:FD*
|
||||
select -assert-count 6 c:fd2 c:fd3 c:fd4 c:fd6 c:fd7 c:fd8
|
||||
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module top(input C, D, output [7:0] Q);
|
||||
FDRE fd1(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[0]));
|
||||
FDSE fd2(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[1]));
|
||||
FDCE fd3(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[2]));
|
||||
FDPE fd4(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[3]));
|
||||
FDRE_1 fd5(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[4]));
|
||||
FDSE_1 fd6(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[5]));
|
||||
FDCE_1 fd7(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[6]));
|
||||
FDPE_1 fd8(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[7]));
|
||||
FDRE #(.INIT(0)) fd1(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[0]));
|
||||
FDSE #(.INIT(0)) fd2(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[1]));
|
||||
FDCE #(.INIT(0)) fd3(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[2]));
|
||||
FDPE #(.INIT(0)) fd4(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[3]));
|
||||
FDRE_1 /*#(.INIT(0))*/ fd5(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[4]));
|
||||
FDSE_1 #(.INIT(0)) fd6(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[5]));
|
||||
FDCE_1 #(.INIT(0)) fd7(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[6]));
|
||||
FDPE_1 #(.INIT(0)) fd8(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[7]));
|
||||
endmodule
|
||||
EOT
|
||||
equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf
|
||||
design -load postopt
|
||||
select -assert-none t:FD*
|
||||
select -assert-count 4 t:FD*
|
||||
select -assert-count 4 c:fd3 c:fd4 c:fd7 c:fd8
|
||||
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module top(input C, D, output [7:0] Q);
|
||||
FDRE #(.INIT(1)) fd1(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[0]));
|
||||
FDSE /*#(.INIT(1))*/ fd2(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[1]));
|
||||
FDCE #(.INIT(1)) fd3(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[2]));
|
||||
FDPE #(.INIT(1)) fd4(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[3]));
|
||||
FDRE_1 #(.INIT(1)) fd5(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[4]));
|
||||
FDSE_1 #(.INIT(1)) fd6(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[5]));
|
||||
FDCE_1 /*#(.INIT(1))*/ fd7(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[6]));
|
||||
FDPE_1 #(.INIT(1)) fd8(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[7]));
|
||||
endmodule
|
||||
EOT
|
||||
logger -expect warning "Module '\$paramod\\FDRE\\INIT=1' contains a \$dff cell .*" 1
|
||||
logger -expect warning "Module '\$paramod\\FDRE_1\\INIT=1' contains a \$dff cell .*" 1
|
||||
logger -expect warning "Module 'FDSE' contains a \$dff cell .*" 1
|
||||
logger -expect warning "Module '\$paramod\\FDSE_1\\INIT=1' contains a \$dff cell .*" 1
|
||||
equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf
|
||||
design -load postopt
|
||||
select -assert-count 8 t:FD*
|
||||
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module top(input clk, clr, pre, output reg q0 = 1'b0, output reg q1 = 1'b1);
|
||||
always @(posedge clk or posedge clr)
|
||||
if (clr)
|
||||
q0 <= 1'b0;
|
||||
else
|
||||
q0 <= ~q0;
|
||||
always @(posedge clk or posedge pre)
|
||||
if (pre)
|
||||
q1 <= 1'b1;
|
||||
else
|
||||
q1 <= ~q1;
|
||||
endmodule
|
||||
EOT
|
||||
proc
|
||||
equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf
|
||||
design -load postopt
|
||||
select -assert-count 1 t:FDCE
|
||||
select -assert-count 1 t:FDPE
|
||||
select -assert-count 2 t:INV
|
||||
select -assert-count 0 t:FD* t:INV %% t:* %D
|
||||
|
||||
logger -expect-no-warnings
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
read_verilog <<EOT
|
||||
module top(input C, CE, D, R, output [1:0] Q);
|
||||
FDRE #(.INIT(1'b1)) ff1 (.C(C), .CE(CE), .D(D), .R(R), .Q(Q[0]));
|
||||
FDRE_1 #(.INIT(1'b1)) ff2 (.C(C), .CE(CE), .D(D), .R(R), .Q(Q[1]));
|
||||
endmodule
|
||||
EOT
|
||||
design -save gold
|
||||
|
||||
techmap -map +/xilinx/abc9_map.v -max_iter 1 -D DFF_MODE
|
||||
techmap -map +/xilinx/abc9_unmap.v
|
||||
select -assert-count 1 t:FDSE
|
||||
select -assert-count 1 t:FDSE_1
|
||||
techmap -autoproc -map +/xilinx/cells_sim.v
|
||||
design -stash gate
|
||||
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
techmap -autoproc -map +/xilinx/cells_sim.v
|
||||
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -seq 2 -verify -prove-asserts -show-ports miter
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module top(input C, CE, D, S, output [1:0] Q);
|
||||
FDSE #(.INIT(1'b1)) ff1 (.C(C), .CE(CE), .D(D), .S(S), .Q(Q[0]));
|
||||
FDSE_1 #(.INIT(1'b1)) ff2 (.C(C), .CE(CE), .D(D), .S(S), .Q(Q[1]));
|
||||
endmodule
|
||||
EOT
|
||||
design -save gold
|
||||
|
||||
techmap -map +/xilinx/abc9_map.v -max_iter 1 -D DFF_MODE
|
||||
techmap -map +/xilinx/abc9_unmap.v
|
||||
select -assert-count 1 t:FDRE
|
||||
select -assert-count 1 t:FDRE_1
|
||||
techmap -autoproc -map +/xilinx/cells_sim.v
|
||||
design -stash gate
|
||||
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
techmap -autoproc -map +/xilinx/cells_sim.v
|
||||
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -seq 2 -set-init-zero -verify -prove-asserts -show-ports miter
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module top(input C, CE, D, PRE, output [1:0] Q);
|
||||
FDPE #(.INIT(1'b1)) ff1 (.C(C), .CE(CE), .D(D), .PRE(PRE), .Q(Q[0]));
|
||||
FDPE_1 #(.INIT(1'b1)) ff2 (.C(C), .CE(CE), .D(D), .PRE(PRE), .Q(Q[1]));
|
||||
endmodule
|
||||
EOT
|
||||
design -save gold
|
||||
|
||||
techmap -map +/xilinx/abc9_map.v -max_iter 1 -D DFF_MODE
|
||||
techmap -map +/xilinx/abc9_unmap.v
|
||||
select -assert-count 1 t:FDCE
|
||||
select -assert-count 1 t:FDCE_1
|
||||
techmap -autoproc -map +/xilinx/cells_sim.v
|
||||
design -stash gate
|
||||
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
techmap -autoproc -map +/xilinx/cells_sim.v
|
||||
clk2fflogic
|
||||
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -seq 2 -set-init-zero -verify -prove-asserts -show-ports miter
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module top(input C, CE, D, CLR, output [1:0] Q);
|
||||
FDCE #(.INIT(1'b1)) ff1 (.C(C), .CE(CE), .D(D), .CLR(CLR), .Q(Q[0]));
|
||||
FDCE_1 #(.INIT(1'b1)) ff2 (.C(C), .CE(CE), .D(D), .CLR(CLR), .Q(Q[1]));
|
||||
endmodule
|
||||
EOT
|
||||
design -save gold
|
||||
|
||||
techmap -map +/xilinx/abc9_map.v -max_iter 1 -D DFF_MODE
|
||||
techmap -map +/xilinx/abc9_unmap.v
|
||||
select -assert-count 1 t:FDPE
|
||||
techmap -autoproc -map +/xilinx/cells_sim.v
|
||||
design -stash gate
|
||||
|
||||
design -import gold -as gold
|
||||
design -import gate -as gate
|
||||
techmap -autoproc -map +/xilinx/cells_sim.v
|
||||
clk2fflogic
|
||||
|
||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
|
||||
sat -seq 2 -set-init-zero -verify -prove-asserts -show-ports miter
|
|
@ -0,0 +1,3 @@
|
|||
MUXF8 1 0 3 1
|
||||
#I0 I1 S
|
||||
0 0 0 # O
|
|
@ -213,7 +213,7 @@ module arbiter (clk, rst, request, acknowledge, grant, grant_valid, grant_encode
|
|||
input rst;
|
||||
endmodule
|
||||
|
||||
(* abc9_box, blackbox *)
|
||||
(* abc9_box_id=1, blackbox *)
|
||||
module MUXF8(input I0, I1, S, output O);
|
||||
specify
|
||||
(I0 => O) = 0;
|
||||
|
|
|
@ -25,7 +25,7 @@ exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v *.sv EXTRA_FLAGS="-n 300 -p
|
|||
synth -run coarse; \
|
||||
opt -full; \
|
||||
techmap; \
|
||||
abc9 -lut 4; \
|
||||
abc9 -lut 4 -box ../abc9.box; \
|
||||
clean; \
|
||||
check -assert; \
|
||||
select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%; \
|
||||
|
|
|
@ -45,14 +45,16 @@ sat -seq 10 -verify -prove-asserts -show-ports miter
|
|||
design -reset
|
||||
read_verilog -icells <<EOT
|
||||
module abc9_test036(input clk, d, output q);
|
||||
(* keep *) reg w;
|
||||
$__ABC9_FF_ ff(.D(d), .Q(w));
|
||||
wire \ff.clock = clk;
|
||||
wire \ff.init = 1'b0;
|
||||
(* keep, init=1'b0 *) wire w;
|
||||
$_DFF_P_ ff(.C(clk), .D(d), .Q(w));
|
||||
assign q = w;
|
||||
endmodule
|
||||
EOT
|
||||
abc9 -lut 4 -dff
|
||||
equiv_opt -assert abc9 -lut 4 -dff
|
||||
design -load postopt
|
||||
cd abc9_test036
|
||||
select -assert-count 1 t:$_DFF_P_
|
||||
select -assert-none t:* t:$_DFF_P_ %d
|
||||
|
||||
|
||||
design -reset
|
||||
|
@ -67,8 +69,32 @@ specify
|
|||
endspecify
|
||||
endmodule
|
||||
|
||||
module top(input [1:0] i, output o);
|
||||
module abc9_test037(input [1:0] i, output o);
|
||||
LUT2 #(.mask(4'b0)) lut (.i(i), .o(o));
|
||||
endmodule
|
||||
EOT
|
||||
abc9
|
||||
|
||||
|
||||
design -reset
|
||||
read_verilog -icells <<EOT
|
||||
module abc9_test038(input clk, output w, x, y, z);
|
||||
(* init=1'b1 *) wire w;
|
||||
$_DFF_N_ ff1(.C(clk), .D(1'b1), .Q(w));
|
||||
(* init=1'bx *) wire x;
|
||||
$_DFF_N_ ff2(.C(clk), .D(1'b0), .Q(x));
|
||||
(* init=1'b0 *) wire y;
|
||||
$_DFF_N_ ff3(.C(clk), .D(1'b0), .Q(y));
|
||||
(* init=1'b0 *) wire z;
|
||||
$_DFF_N_ ff4(.C(clk), .D(1'b1), .Q(z));
|
||||
endmodule
|
||||
EOT
|
||||
simplemap
|
||||
equiv_opt abc9 -lut 4 -dff
|
||||
design -load postopt
|
||||
cd abc9_test038
|
||||
select -assert-count 3 t:$_DFF_N_
|
||||
select -assert-none c:ff1 c:ff2 c:ff4 %% c:* %D
|
||||
clean
|
||||
select -assert-count 2 a:init
|
||||
select -assert-none w:w w:z %% a:init %D
|
||||
|
|
Loading…
Reference in New Issue