9 namespace xilinx_toolbox
13 u32 deleted_gates = 0;
15 std::vector<Gate*> to_delete;
20 const auto lut6_2_gates = nl->
get_gates([](
const Gate* g) {
return g->
get_type()->get_name() ==
"LUT6_2"; });
22 for (
const auto& g : lut6_2_gates)
29 if (init_get_res.is_error())
31 log_warning(
"xilinx_toolbox",
"could not get INIT string of gate '{}' with ID {}, skipping this gate.", g->
get_name(), g->
get_id());
34 auto init = init_get_res.get().front();
35 if (init.length() != 16)
37 log_warning(
"xilinx_toolbox",
"INIT string '{}' has length {}, expected 16.", init, init.length());
41 if (o5->get_num_of_destinations() > 0)
45 lut5->
set_data(
"xilinx_preprocessing_information",
"original_init",
"string", init);
47 auto init_O5 = init.substr(8, 8);
48 if (lut5->set_init_data({init_O5}).is_error())
50 log_warning(
"xilinx_toolbox",
"could not set INIT string of gate '{}' with ID {}, skipping this gate.", lut5->get_name(), lut5->get_id());
55 mod->assign_gate(lut5);
60 in_ep->get_net()->add_destination(lut5, in_ep->get_pin()->get_name());
64 o5->add_source(lut5,
"O");
67 if (o6->get_num_of_destinations() > 0)
71 lut6->
set_data(
"xilinx_preprocessing_information",
"original_init",
"string", init);
73 if (lut6->set_init_data({init}).is_error())
75 log_warning(
"xilinx_toolbox",
"could not set INIT string of gate '{}' with ID {}, skipping this gate.", lut6->get_name(), lut6->get_id());
82 mod->assign_gate(lut6);
87 in_ep->get_net()->add_destination(lut6, in_ep->get_pin()->get_name());
91 o6->add_source(lut6,
"O");
93 to_delete.push_back(g);
96 for (
const auto& g : to_delete)
100 return ERR(
"Cannot split luts for netlist with ID " + std::to_string(nl->
get_id()) +
": Failed to delete gate " + g->
get_name() +
" with ID " + std::to_string(g->
get_id()));
108 log_info(
"xilinx_toolbox",
"split {} LUT6_2 gates into {} LUT6 and LUT5 gates", deleted_gates, new_gates);
109 return OK(deleted_gates);
114 u32 deleted_gates = 0;
116 std::vector<Gate*> to_delete;
119 if (ff_gt ==
nullptr)
121 return ERR(
"could not find gate type 'FDE' in gate library");
125 for (
const auto& gate : nl->
get_gates([](
const auto& g) { return g->get_type()->get_name() ==
"SRL16E" || g->get_type()->get_name() ==
"SRLC32E"; }))
128 if (control_pins.size() != 4 && gate->get_type()->get_name() ==
"SRLC16E" || control_pins.size() != 5 && gate->get_type()->get_name() ==
"SRLC32E")
130 return ERR(
"invalid number of control pins");
133 if (gate->get_type()->get_name() ==
"SRL16E")
135 std::sort(control_pins.begin(), control_pins.end(), [](
const auto& p1,
const auto& p2) {
136 const u32 idx1 = std::stoull(p1->get_name().substr(1));
137 const u32 idx2 = std::stoull(p2->get_name().substr(1));
144 std::sort(control_pins.begin(), control_pins.end(), [](
const auto& p1,
const auto& p2) {
145 const u32 idx1 = std::stoull(p1->get_name().substr(2));
146 const u32 idx2 = std::stoull(p2->get_name().substr(2));
152 u32 select_value = 0;
153 for (
u32 idx = 0; idx < control_pins.size(); idx++)
155 const Net* cn = gate->get_fan_in_net(control_pins.at(idx));
159 log_warning(
"xilinx_toolbox",
"control net at pin '{}' of gate '{}' with ID {} is 'nullptr'", control_pins.at(idx)->get_name(), gate->get_name(), gate->get_id());
165 log_warning(
"xilinx_toolbox",
"control net at pin '{}' of gate '{}' with ID {} is not constant", control_pins.at(idx)->get_name(), gate->get_name(), gate->get_id());
169 select_value += (cn->
is_gnd_net() ? 0 : 1) << idx;
172 const auto clock_pins = gate->get_type()->get_pins([](
const auto& p) {
return (p->get_direction() ==
PinDirection::input) && (p->get_type() ==
PinType::clock); });
173 if (clock_pins.size() != 1)
175 return ERR(
"invalid number of input clock pins at shift register gate '" + gate->get_name() +
"' with ID " + std::to_string(gate->get_id()));
179 if (enable_pins.size() != 1)
181 return ERR(
"invalid number of input enable pins at shift register gate '" + gate->get_name() +
"' with ID " + std::to_string(gate->get_id()));
184 const auto data_pins = gate->get_type()->get_pins([](
const auto& p) {
return (p->get_direction() ==
PinDirection::input) && (p->get_type() ==
PinType::data); });
185 if (data_pins.size() != 1)
187 return ERR(
"invalid number of input data pins at shift register gate '" + gate->get_name() +
"' with ID " + std::to_string(gate->get_id()));
190 Net* clk_in = gate->get_fan_in_net(clock_pins.front());
191 Net* enable_in = gate->get_fan_in_net(enable_pins.front());
192 Net* data_in = gate->get_fan_in_net(data_pins.front());
193 Net* state_out =
nullptr;
194 Net* max_state_out =
nullptr;
196 if (gate->get_type()->get_name() ==
"SRLC32E")
198 state_out = gate->get_fan_out_net(
"Q");
199 max_state_out = gate->get_fan_out_net(
"Q31");
203 state_out = gate->get_fan_out_net(
"Q");
206 if (clk_in ==
nullptr)
208 return ERR(
"no clock input net connected to shift register gate '" + gate->get_name() +
"' with ID " + std::to_string(gate->get_id()));
211 if (enable_in ==
nullptr)
213 return ERR(
"no enable input net connected to shift register gate '" + gate->get_name() +
"' with ID " + std::to_string(gate->get_id()));
216 if (data_in ==
nullptr)
218 return ERR(
"no data input net connected to shift register gate '" + gate->get_name() +
"' with ID " + std::to_string(gate->get_id()));
221 if (state_out ==
nullptr && max_state_out ==
nullptr)
223 return ERR(
"no state output net connected to shift register gate '" + gate->get_name() +
"' with ID " + std::to_string(gate->get_id()));
226 u32 register_size = 0;
227 std::vector<Gate*> flip_flops;
228 std::vector<Net*> state_nets;
230 if (max_state_out !=
nullptr)
236 register_size = select_value;
239 for (
u32 ff_idx = 0; ff_idx <= register_size; ff_idx++)
241 const std::string ff_name = gate->get_name() +
"_split_ff_" + std::to_string(ff_idx);
254 state_nets.back()->add_destination(new_gate,
"D");
257 if (ff_idx == select_value && state_out !=
nullptr)
260 state_nets.push_back(state_out);
262 else if (ff_idx == register_size && max_state_out !=
nullptr)
265 state_nets.push_back(max_state_out);
271 state_nets.push_back(new_net);
275 to_delete.push_back(gate);
278 for (
const auto& g : to_delete)
282 return ERR(
"Cannot split shift register primitives for netlist with ID " + std::to_string(nl->
get_id()) +
": Failed to delete gate " + g->get_name() +
" with ID "
283 + std::to_string(g->get_id()));
291 log_info(
"xilinx_toolbox",
"split {} SRL16E/SRLC32E gates into {} flip-flops", deleted_gates, new_gates);
293 return OK(deleted_gates);
bool set_data(const std::string &category, const std::string &key, const std::string &data_type, const std::string &value, const bool log_with_info_level=false)
Net * get_fan_in_net(const std::string &pin_name) const
GateType * get_type() const
Net * get_fan_out_net(const std::string &pin_name) const
const std::string & get_name() const
Module * get_module() const
const std::vector< Endpoint * > & get_fan_in_endpoints() const
Result< std::vector< std::string > > get_init_data() const
GateType * get_gate_type_by_name(const std::string &name) const
bool is_top_module() const
Endpoint * add_destination(Gate *gate, const std::string &pin_name)
Endpoint * add_source(Gate *gate, const std::string &pin_name)
u32 get_num_of_destinations(const std::function< bool(Endpoint *ep)> &filter=nullptr) const
const std::vector< Gate * > & get_gates() const
Net * create_net(const u32 net_id, const std::string &name)
bool delete_gate(Gate *gate)
Gate * create_gate(const u32 gate_id, GateType *gate_type, const std::string &name="", i32 x=-1, i32 y=-1)
const GateLibrary * get_gate_library() const
#define log_info(channel,...)
#define log_warning(channel,...)