From 475d983676a42e57a104aaf5e72462d704c0c3aa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 10 Jan 2020 14:49:52 -0800 Subject: [PATCH] abc9_ops -prep_times: generate flop boxes from abc9_required attr --- passes/techmap/abc9_ops.cc | 84 ++++++++++++++++++++++++++++-------- techlibs/xilinx/abc9_xc7.box | 61 -------------------------- 2 files changed, 67 insertions(+), 78 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 14b3f6c43..918afd284 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -39,9 +39,13 @@ void check(RTLIL::Design *design) { dict box_lookup; for (auto m : design->modules()) { + auto flop = m->get_bool_attribute(ID(abc9_flop)); auto it = m->attributes.find(ID(abc9_box_id)); - if (it == m->attributes.end()) + if (it == m->attributes.end()) { + if (flop) + log_error("Module '%s' contains (* abc9_flop *) but not (* abc9_box_id= *).\n", log_id(m)); continue; + } if (m->name.begins_with("$paramod")) continue; auto id = it->second.as_int(); @@ -59,21 +63,31 @@ void check(RTLIL::Design *design) if (w->get_bool_attribute("\\abc9_carry")) { if (w->port_input) { if (carry_in != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); + log_error("Module '%s' contains more than one (* abc9_carry *) input port.\n", log_id(m)); carry_in = port_name; } if (w->port_output) { if (carry_out != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(m)); + log_error("Module '%s' contains more than one (* abc9_carry *) output port.\n", log_id(m)); carry_out = port_name; } } } if (carry_in != IdString() && carry_out == IdString()) - log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m)); + log_error("Module '%s' contains an (* abc9_carry *) input port but no output port.\n", log_id(m)); if (carry_in == IdString() && carry_out != IdString()) - log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); + log_error("Module '%s' contains an (* abc9_carry *) output port but no input port.\n", log_id(m)); + + if (flop) { + int num_outputs = 0; + for (auto port_name : m->ports) { + auto wire = m->wire(port_name); + if (wire->port_output) num_outputs++; + } + if (num_outputs != 1) + log_error("Module '%s' with (* abc_flop *) has %d outputs (expect 1).\n", log_id(m), num_outputs); + } } } @@ -464,12 +478,10 @@ void prep_holes(RTLIL::Module *module, bool dff) void prep_times(RTLIL::Design *design) { std::set delays; + pool flops; std::vector boxes; std::map> requireds; for (auto module : design->selected_modules()) { - if (module->get_bool_attribute("\\abc9_holes")) - continue; - if (module->processes.size() > 0) { log("Skipping module %s as it contains processes.\n", log_id(module)); continue; @@ -485,10 +497,13 @@ void prep_times(RTLIL::Design *design) continue; if (!inst_module->get_blackbox_attribute()) continue; - // Only flop boxes are not combinatorial and may have required times, - // however those times are captured by this flop box, no need to - // add delay boxes - if (cell->attributes.count(ID(abc9_box_id))) + if (inst_module->get_bool_attribute(ID(abc9_flop))) { + flops.insert(inst_module); + continue; + } + // All remaining boxes are combinatorial and cannot + // contain a required time + if (inst_module->attributes.count(ID(abc9_box_id))) continue; boxes.emplace_back(cell); } @@ -536,15 +551,48 @@ void prep_times(RTLIL::Design *design) std::stringstream ss; bool first = true; - for (auto d : delays) - if (first) { + for (auto d : delays) { + if (first) first = false; - ss << d; - } else - ss << " " << d; + ss << " "; + ss << d; + } module->attributes[ID(abc9_delays)] = ss.str(); } + + std::stringstream ss; + for (auto flop_module : flops) { + // Skip parameterised flop_modules for now (since we do not + // dynamically generate the abc9_box_id) + if (flop_module->name.begins_with("$paramod")) + continue; + + int num_inputs = 0, num_outputs = 0; + for (auto port_name : flop_module->ports) { + auto wire = flop_module->wire(port_name); + if (wire->port_input) num_inputs++; + if (wire->port_output) num_outputs++; + } + log_assert(num_outputs == 1); + + ss << log_id(flop_module) << " " << flop_module->attributes.at(ID(abc9_box_id)).as_int(); + ss << " 1 " << num_inputs+1 << " " << num_outputs << std::endl; + bool first = true; + for (auto port_name : flop_module->ports) { + auto wire = flop_module->wire(port_name); + if (!wire->port_input) + continue; + if (first) + first = false; + else + ss << " "; + ss << wire->attributes.at("\\abc9_required", 0).as_int(); + } + // Last input is 'abc9_ff.Q' + ss << " 0" << std::endl << std::endl; + } + design->scratchpad_set_string("abc9_ops.box.flops", ss.str()); } void write_box(RTLIL::Module *module, const std::string &src, const std::string &dst) { @@ -559,6 +607,8 @@ void write_box(RTLIL::Module *module, const std::string &src, const std::string ifs.close(); } + ofs << module->design->scratchpad_get_string("abc9_ops.box.flops"); + auto it = module->attributes.find(ID(abc9_delays)); if (it != module->attributes.end()) { for (const auto &tok : split_tokens(it->second.decode_string())) { diff --git a/techlibs/xilinx/abc9_xc7.box b/techlibs/xilinx/abc9_xc7.box index 13f4f0e61..48d492801 100644 --- a/techlibs/xilinx/abc9_xc7.box +++ b/techlibs/xilinx/abc9_xc7.box @@ -62,67 +62,6 @@ $__ABC9_ASYNC1 1001 1 2 1 #A S 0 764 # Y -# Flop boxes: -# * Max delays from https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L237-L251 -# https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L265-L277 -# * Exception: $abc9_currQ is a special input (located last) necessary for clock-enable functionality - -# Box 1100 : FDRE -# name ID w/b ins outs -FDRE 1100 1 5 1 -#C CE D R $abc9_currQ -#0 109 -46 404 0 -0 109 0 404 0 # Q (-46ps Tsu clamped to 0) - -# Box 1101 : FDRE_1 -# name ID w/b ins outs -FDRE_1 1101 1 5 1 -#C CE D R $abc9_currQ -#0 109 -46 404 0 -0 109 0 404 0 # Q (-46ps Tsu clamped to 0) - -# Box 1102 : FDSE -# name ID w/b ins outs -FDSE 1102 1 5 1 -#C CE D R $abc9_currQ -#0 109 -46 404 0 -0 109 0 404 0 # Q (-46ps Tsu clamped to 0) - -# Box 1103 : FDSE_1 -# name ID w/b ins outs -FDSE_1 1103 1 5 1 -#C CE D R $abc9_currQ -#0 109 -46 404 0 -0 109 0 404 0 # Q (-46ps Tsu clamped to 0) - -# Box 1104 : FDCE -# name ID w/b ins outs -FDCE 1104 1 5 1 -#C CE CLR D $abc9_currQ -#0 109 764 -46 0 -0 109 764 0 0 # Q (-46ps Tsu clamped to 0) - -# Box 1105 : FDCE_1 -# name ID w/b ins outs -FDCE_1 1105 1 5 1 -#C CE CLR D $abc9_currQ -#0 109 764 -46 0 -0 109 764 0 0 # Q (-46ps Tsu clamped to 0) - -# Box 1106 : FDPE -# name ID w/b ins outs -FDPE 1106 1 5 1 -#C CE D PRE $abc9_currQ -#0 109 -46 764 0 -0 109 0 764 0 # Q (-46ps Tsu clamped to 0) - -# Box 1107 : FDPE_1 -# name ID w/b ins outs -FDPE_1 1107 1 5 1 -#C CE D PRE $abc9_currQ -#0 109 -46 764 0 -0 109 0 764 0 # Q (-46ps Tsu clamped to 0) - # Box 2000 : $__ABC9_LUT6 # (private cell to emulate async behaviour of LUTRAMs) # SLICEM/A6LUT -- 2.30.2