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:
Eddie Hung 2020-05-18 08:06:50 -07:00 committed by GitHub
commit 2d573a0ff6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 1663 additions and 1860 deletions

View File

@ -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()) {

View File

@ -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;

View File

@ -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();

View File

@ -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)

View File

@ -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)];

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,5 +0,0 @@
// ---------------------------------------
module \$__ABC9_DPR16X4_COMB (input [3:0] $DO, RAD, output [3:0] DO);
assign DO = $DO;
endmodule

View File

@ -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
// ---------------------------------------

View File

@ -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");
}

View File

@ -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))

View File

@ -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

View File

@ -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,

28
techlibs/ice40/ff_map.v Normal file
View File

@ -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

View File

@ -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");
}

View File

@ -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");

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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";

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,3 @@
MUXF8 1 0 3 1
#I0 I1 S
0 0 0 # O

View File

@ -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;

View File

@ -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_ %%; \

View File

@ -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