14 LUTComponent::LUTComponent(std::unordered_map<std::string, LUTOutputConfig> configs) : m_output_pin_configs(
std::move(configs))
18 std::unique_ptr<LUTComponent> LUTComponent::create(std::unordered_map<std::string, LUTOutputConfig> configs)
20 for (
auto it = configs.begin(); it != configs.end();)
22 const u32 bc = it->second.bit_count;
23 if (bc == 0 || (bc & (bc - 1)) != 0)
25 log_error(
"lut_component",
"cannot add output pin config for pin '{}': bit_count {} must be a non-zero power of two — skipping.", it->first, bc);
26 it = configs.erase(it);
28 else if (it->second.input_pins.empty())
30 log_error(
"lut_component",
"cannot add output pin config for pin '{}': input_pins must be non-empty — skipping.", it->first);
31 it = configs.erase(it);
38 return std::unique_ptr<LUTComponent>(
new LUTComponent(std::move(configs)));
48 return component->
get_type() == m_type;
51 std::vector<GateTypeComponent*> LUTComponent::get_components(
const std::function<
bool(
const GateTypeComponent*)>& filter)
const
58 if (
auto it = m_output_pin_configs.find(pin_name); it != m_output_pin_configs.end())
65 const std::unordered_map<std::string, LUTComponent::LUTOutputConfig>& LUTComponent::get_output_pin_configs()
const
67 return m_output_pin_configs;
74 return ERR(
"bit_count must be non-zero");
79 return ERR(
"INIT string is empty");
82 const size_t min_chars = (
static_cast<size_t>(bit_offset) + bit_count + 3) / 4;
83 if (full_hex.size() < min_chars)
85 return ERR(
"INIT string '" + full_hex +
"' is too short: need at least " + std::to_string(min_chars) +
" hex char(s) to cover slice [" + std::to_string(bit_offset) +
", "
86 + std::to_string(bit_offset + bit_count) +
"), got " + std::to_string(full_hex.size()));
92 full_val = std::stoull(full_hex,
nullptr, 16);
94 catch (
const std::invalid_argument&)
96 return ERR(
"INIT string '" + full_hex +
"' is not a valid hex value");
98 catch (
const std::out_of_range&)
100 return ERR(
"INIT string '" + full_hex +
"' is out of range for u64");
103 const u64 mask = (bit_count >= 64) ? std::numeric_limits<u64>::max() : ((1ULL << bit_count) - 1);
104 const u64 sliced = (full_val >> bit_offset) & mask;
106 std::stringstream ss;
107 ss << std::hex << std::uppercase << std::setfill('0') << std::setw(static_cast<int>((bit_count + 3) / 4)) << sliced;
111 Result<std::string> LUTComponent::splice_init_slice(
const std::string& full_hex,
const std::string& slice_hex,
u32 bit_offset,
u32 bit_count)
115 return ERR(
"bit_count must be non-zero");
119 if (!full_hex.empty())
123 existing = std::stoull(full_hex,
nullptr, 16);
125 catch (
const std::invalid_argument&)
127 return ERR(
"full INIT string '" + full_hex +
"' is not a valid hex value");
129 catch (
const std::out_of_range&)
131 return ERR(
"full INIT string '" + full_hex +
"' is out of range for u64");
138 new_slice = std::stoull(slice_hex,
nullptr, 16);
140 catch (
const std::invalid_argument&)
142 return ERR(
"slice value '" + slice_hex +
"' is not a valid hex value");
144 catch (
const std::out_of_range&)
146 return ERR(
"slice value '" + slice_hex +
"' is out of range for u64");
149 const u64 mask = (bit_count >= 64) ? std::numeric_limits<u64>::max() : ((1ULL << bit_count) - 1);
150 const u64 spliced = (existing & ~(mask << bit_offset)) | ((new_slice & mask) << bit_offset);
152 const int width = full_hex.empty() ?
static_cast<int>((bit_offset + bit_count + 3) / 4) :
static_cast<int>(full_hex.size());
154 std::stringstream ss;
155 ss << std::hex << std::uppercase << std::setfill(
'0') << std::setw(width) << spliced;
161 std::string lut_param_read(
const Gate* gate,
const std::string& key)
168 return (pv.size() >= 2 && pv[0] ==
'0' && pv[1] ==
'x') ? pv.substr(2) : pv;
176 return ERR(
"gate is nullptr");
181 return ERR(
"pin '" + pin_name +
"' does not exist on gate type '" + gate->
get_type()->
get_name() +
"'");
183 return get_init_string(gate, pin);
190 return ERR(
"gate is nullptr");
194 return ERR(
"pin is nullptr");
196 if (pin->
get_type() != PinType::lut)
198 return ERR(
"pin '" + pin->
get_name() +
"' is not of type PinType::lut");
201 if (dir != PinDirection::output && dir != PinDirection::internal)
203 return ERR(
"pin '" + pin->
get_name() +
"' must have direction output or internal");
208 return ERR(
"pin '" + pin->
get_name() +
"' has no INIT config");
210 const std::string full_str = lut_param_read(gate, cfg->
init_identifier);
214 return ERR(
"could not get INIT string for gate '" + gate->
get_name() +
"': " + res.get_error().get());
216 return OK(res.get());
223 return ERR(
"gate is nullptr");
228 return ERR(
"pin '" + pin_name +
"' does not exist on gate type '" + gate->
get_type()->
get_name() +
"'");
230 return set_init_string(gate, pin, hex);
237 return ERR(
"gate is nullptr");
241 return ERR(
"pin is nullptr");
243 if (pin->
get_type() != PinType::lut)
245 return ERR(
"pin '" + pin->
get_name() +
"' is not of type PinType::lut");
248 if (dir != PinDirection::output && dir != PinDirection::internal)
250 return ERR(
"pin '" + pin->
get_name() +
"' must have direction output or internal");
255 return ERR(
"pin '" + pin->
get_name() +
"' has no INIT config");
257 if (hex.empty() || !std::all_of(hex.begin(), hex.end(), [](
unsigned char c) { return std::isxdigit(c); }))
259 return ERR(
"'" + hex +
"' is not a valid hex string");
261 const size_t expected_chars = (
static_cast<size_t>(cfg->
bit_count) + 3) / 4;
262 if (hex.size() != expected_chars)
264 return ERR(
"hex string '" + hex +
"' has wrong length: expected " + std::to_string(expected_chars) +
" characters for " + std::to_string(cfg->
bit_count) +
" bits");
267 const std::string existing_str = lut_param_read(gate, cfg->
init_identifier);
271 return ERR(
"could not set INIT string for gate '" + gate->
get_name() +
"': " + res.get_error().get());
274 const std::string spliced_str = res.get();
275 const std::string value =
"0x" + spliced_str;
276 const size_t nbits = spliced_str.size() * 4;
277 auto param_res = Parameter::BitVector(cfg->
init_identifier,
static_cast<u16>(nbits),
"");
278 if (param_res.is_error())
280 return ERR(
"could not create parameter: " + param_res.get_error().get());
const std::string & get_name() const
PinDirection get_direction() const
Result< std::string > get_parameter_value(const std::string &name) const
bool has_parameter(const Parameter ¶m) const
Result< std::monostate > set_parameter(const Parameter ¶m, const std::string &value)
GateType * get_type() const
const std::string & get_name() const
virtual ComponentType get_type() const =0
const std::string & get_name() const
GatePin * get_pin_by_name(const std::string &name) const
#define log_error(channel,...)
std::string init_identifier