12 #include "rapidjson/filewritestream.h"
13 #include "rapidjson/prettywriter.h"
22 if (gate_lib ==
nullptr)
24 log_error(
"hgl_writer",
"received a nullptr as gate library.", file_path.string());
28 FILE* fp = fopen(file_path.string().c_str(),
"w");
31 log_error(
"hgl_writer",
"unable to open '{}' for writing.", file_path.string());
35 rapidjson::Document document;
38 if (!write_gate_library(document, gate_lib))
44 char writeBuffer[65536];
45 rapidjson::FileWriteStream os(fp, writeBuffer,
sizeof(writeBuffer));
47 rapidjson::PrettyWriter<rapidjson::FileWriteStream> writer(os);
48 document.Accept(writer);
55 bool HGLWriter::write_gate_library(rapidjson::Document& document,
const GateLibrary* gate_lib)
57 rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
60 document.AddMember(
"version", HGL_FORMAT_VERSION, allocator);
63 document.AddMember(
"library", gate_lib->
get_name(), allocator);
66 rapidjson::Value gate_locs(rapidjson::kObjectType);
69 gate_locs.AddMember(
"data_x_identifier", location_identifiers.first, allocator);
70 gate_locs.AddMember(
"data_y_identifier", location_identifiers.second, allocator);
71 document.AddMember(
"gate_locations", gate_locs, allocator);
74 std::vector<GateType*> gate_types;
78 if ((gt.first !=
"HAL_GND") && (gt.first !=
"HAL_VDD"))
80 gate_types.push_back(gt.second);
84 std::sort(gate_types.begin(), gate_types.end(), [](GateType* l, GateType* r) { return l->get_id() < r->get_id(); });
86 rapidjson::Value cells(rapidjson::kArrayType);
87 for (
const auto gt : gate_types)
89 rapidjson::Value cell(rapidjson::kObjectType);
92 cell.AddMember(
"name", gt->get_name(), allocator);
95 std::set<GateTypeProperty> properties = gt->get_properties();
97 rapidjson::Value bts(rapidjson::kArrayType);
99 for (
const auto& property : properties)
101 std::string bt_str = enum_to_string<GateTypeProperty>(property);
102 bts.PushBack(rapidjson::Value{}.SetString(bt_str.c_str(), bt_str.length(), allocator), allocator);
105 cell.AddMember(
"types", bts, allocator);
107 std::unordered_map<std::string, BooleanFunction> functions = gt->get_boolean_functions();
110 if (LUTComponent* lut_component = gt->get_component_as<LUTComponent>([](
const GateTypeComponent* c) { return LUTComponent::is_class_of(c); }); lut_component !=
nullptr)
112 rapidjson::Value lut_config(rapidjson::kObjectType);
114 InitComponent* init_component = lut_component->get_component_as<InitComponent>([](
const GateTypeComponent* c) {
return InitComponent::is_class_of(c); });
115 if (init_component ==
nullptr)
117 log_error(
"hgl_writer",
"missing InitComponent for LUT initialization data of gate type '{}'.", gt->get_name());
122 if (lut_component->is_init_ascending())
124 lut_config.AddMember(
"bit_order",
"ascending", allocator);
128 lut_config.AddMember(
"bit_order",
"descending", allocator);
132 lut_config.AddMember(
"data_category", init_component->get_init_category(), allocator);
133 lut_config.AddMember(
"data_identifier", init_component->get_init_identifiers().front(), allocator);
135 cell.AddMember(
"lut_config", lut_config, allocator);
137 else if (FFComponent* ff_component = gt->get_component_as<FFComponent>([](
const GateTypeComponent* c) { return FFComponent::is_class_of(c); }); ff_component !=
nullptr)
139 rapidjson::Value ff_config(rapidjson::kObjectType);
141 StateComponent* state_component = ff_component->get_component_as<StateComponent>([](
const GateTypeComponent* c) {
return StateComponent::is_class_of(c); });
142 if (state_component ==
nullptr)
144 log_error(
"hgl_writer",
"missing StateComponent for FF state identifiers of gate type '{}'.", gt->get_name());
148 ff_config.AddMember(
"state", state_component->get_state_identifier(), allocator);
149 ff_config.AddMember(
"neg_state", state_component->get_neg_state_identifier(), allocator);
151 InitComponent* init_component = state_component->get_component_as<InitComponent>([](
const GateTypeComponent* c) {
return InitComponent::is_class_of(c); });
152 if (init_component !=
nullptr)
155 ff_config.AddMember(
"data_category", init_component->get_init_category(), allocator);
156 ff_config.AddMember(
"data_identifier", init_component->get_init_identifiers().front(), allocator);
160 ff_config.AddMember(
"next_state", ff_component->get_next_state_function().to_string(), allocator);
161 ff_config.AddMember(
"clocked_on", ff_component->get_clock_function().to_string(), allocator);
162 if (BooleanFunction bf = ff_component->get_async_reset_function(); !bf.is_empty())
164 ff_config.AddMember(
"clear_on", bf.to_string(), allocator);
166 if (BooleanFunction bf = ff_component->get_async_set_function(); !bf.is_empty())
168 ff_config.AddMember(
"preset_on", bf.to_string(), allocator);
171 std::pair<AsyncSetResetBehavior, AsyncSetResetBehavior> cp_behav = ff_component->get_async_set_reset_behavior();
174 ff_config.AddMember(
"state_clear_preset", enum_to_string<AsyncSetResetBehavior>(cp_behav.first), allocator);
178 ff_config.AddMember(
"neg_state_clear_preset", enum_to_string<AsyncSetResetBehavior>(cp_behav.second), allocator);
181 cell.AddMember(
"ff_config", ff_config, allocator);
183 else if (LatchComponent* latch_component = gt->get_component_as<LatchComponent>([](
const GateTypeComponent* c) { return LatchComponent::is_class_of(c); }); latch_component !=
nullptr)
185 rapidjson::Value latch_config(rapidjson::kObjectType);
187 StateComponent* state_component = latch_component->get_component_as<StateComponent>([](
const GateTypeComponent* c) {
return StateComponent::is_class_of(c); });
188 if (state_component ==
nullptr)
190 log_error(
"hgl_writer",
"missing StateComponent for latch state identifiers of gate type '{}'.", gt->get_name());
194 latch_config.AddMember(
"state", state_component->get_state_identifier(), allocator);
195 latch_config.AddMember(
"neg_state", state_component->get_neg_state_identifier(), allocator);
198 if (BooleanFunction bf = latch_component->get_data_in_function(); !bf.is_empty())
200 latch_config.AddMember(
"data_in", bf.to_string(), allocator);
202 if (BooleanFunction bf = latch_component->get_enable_function(); !bf.is_empty())
204 latch_config.AddMember(
"enable_on", bf.to_string(), allocator);
206 if (BooleanFunction bf = latch_component->get_async_reset_function(); !bf.is_empty())
208 latch_config.AddMember(
"clear_on", bf.to_string(), allocator);
210 if (BooleanFunction bf = latch_component->get_async_set_function(); !bf.is_empty())
212 latch_config.AddMember(
"preset_on", bf.to_string(), allocator);
215 std::pair<AsyncSetResetBehavior, AsyncSetResetBehavior> cp_behav = latch_component->get_async_set_reset_behavior();
218 latch_config.AddMember(
"state_clear_preset", enum_to_string<AsyncSetResetBehavior>(cp_behav.first), allocator);
222 latch_config.AddMember(
"neg_state_clear_preset", enum_to_string<AsyncSetResetBehavior>(cp_behav.second), allocator);
225 cell.AddMember(
"latch_config", latch_config, allocator);
227 else if (RAMComponent* ram_component = gt->get_component_as<RAMComponent>([](
const GateTypeComponent* c) { return RAMComponent::is_class_of(c); }); ram_component !=
nullptr)
229 rapidjson::Value ram_config(rapidjson::kObjectType);
231 InitComponent* init_component = ram_component->get_component_as<InitComponent>([](
const GateTypeComponent* c) {
return InitComponent::is_class_of(c); });
232 if (init_component ==
nullptr)
238 ram_config.AddMember(
"data_category", init_component->get_init_category(), allocator);
240 rapidjson::Value identifiers(rapidjson::kArrayType);
241 for (
const std::string& identifier : init_component->get_init_identifiers())
243 identifiers.PushBack(rapidjson::Value{}.SetString(identifier.c_str(), identifier.length(), allocator), allocator);
245 ram_config.AddMember(
"data_identifiers", identifiers, allocator);
246 ram_config.AddMember(
"bit_size", ram_component->get_bit_size(), allocator);
248 rapidjson::Value ram_ports(rapidjson::kArrayType);
249 for (
const GateTypeComponent* component : ram_component->get_components([](
const GateTypeComponent* c) { return RAMPortComponent::is_class_of(c); }))
251 const RAMPortComponent* port_component = component->convert_to<RAMPortComponent>();
252 if (port_component ==
nullptr)
257 rapidjson::Value port(rapidjson::kObjectType);
258 port.AddMember(
"data_group", port_component->get_data_group(), allocator);
259 port.AddMember(
"address_group", port_component->get_address_group(), allocator);
260 port.AddMember(
"clocked_on", port_component->get_clock_function().to_string(), allocator);
261 port.AddMember(
"enabled_on", port_component->get_enable_function().to_string(), allocator);
262 port.AddMember(
"is_write", port_component->is_write_port(), allocator);
263 ram_ports.PushBack(port, allocator);
265 ram_config.AddMember(
"ram_ports", ram_ports, allocator);
266 cell.AddMember(
"ram_config", ram_config, allocator);
270 const auto pin_groups = gt->get_pin_groups();
271 rapidjson::Value pg_array(rapidjson::kArrayType);
272 for (
const auto* group : pin_groups)
274 rapidjson::Value pg_val(rapidjson::kObjectType);
275 pg_val.AddMember(
"name", group->get_name(), allocator);
276 pg_val.AddMember(
"direction",
enum_to_string(group->get_direction()), allocator);
277 pg_val.AddMember(
"type",
enum_to_string(group->get_type()), allocator);
278 pg_val.AddMember(
"ascending", group->is_ascending(), allocator);
279 pg_val.AddMember(
"start_index", group->get_start_index(), allocator);
280 pg_val.AddMember(
"ordered", group->is_ordered(), allocator);
283 rapidjson::Value p_array(rapidjson::kArrayType);
284 for (
const auto* pin : group->get_pins())
286 rapidjson::Value p_val(rapidjson::kObjectType);
287 p_val.AddMember(
"name", pin->get_name(), allocator);
288 p_val.AddMember(
"direction",
enum_to_string(pin->get_direction()), allocator);
289 p_val.AddMember(
"type",
enum_to_string(pin->get_type()), allocator);
294 if (
const auto it = functions.find(pin->get_name()); it != functions.end())
296 p_val.AddMember(
"function", it->second.to_string(), allocator);
299 if (
const auto it = functions.find(pin->get_name() +
"_undefined"); it != functions.end())
301 p_val.AddMember(
"x_function", it->second.to_string(), allocator);
304 if (
const auto it = functions.find(pin->get_name() +
"_tristate"); it != functions.end())
306 p_val.AddMember(
"z_function", it->second.to_string(), allocator);
310 p_array.PushBack(p_val, allocator);
313 pg_val.AddMember(
"pins", p_array, allocator);
314 pg_array.PushBack(pg_val, allocator);
317 cell.AddMember(
"pin_groups", pg_array, allocator);
318 cells.PushBack(cell, allocator);
321 document.AddMember(
"cells", cells, allocator);
326 std::vector<HGLWriter::PinCtx> HGLWriter::get_pins(GateType* gt,
const std::unordered_map<std::string, BooleanFunction>& functions)
328 std::vector<PinCtx> res;
329 for (
const auto* pin : gt->get_pins())
332 res_pin.name = pin->get_name();
338 if (
const auto it = functions.find(pin->get_name()); it != functions.end())
340 res_pin.function = it->second.to_string();
343 if (
const auto it = functions.find(pin->get_name() +
"_undefined"); it != functions.end())
345 res_pin.x_function = it->second.to_string();
348 if (
const auto it = functions.find(pin->get_name() +
"_tristate"); it != functions.end())
350 res_pin.z_function = it->second.to_string();
354 res.push_back(res_pin);
const std::pair< std::string, std::string > & get_gate_location_data_identifiers() const
std::unordered_map< std::string, GateType * > get_gate_types(const std::function< bool(const GateType *)> &filter=nullptr) const
std::string get_name() const
const std::string & get_gate_location_data_category() const
bool write(const GateLibrary *gate_lib, const std::filesystem::path &file_path) override
static bool is_class_of(const GateTypeComponent *component)
static bool is_class_of(const GateTypeComponent *component)
#define log_error(channel,...)
std::string enum_to_string(T e)