From 5f94cb1de427232502bd46a71d9b975e33923c89 Mon Sep 17 00:00:00 2001 From: SJulianS Date: Tue, 2 Mar 2021 11:32:08 +0100 Subject: [PATCH 1/5] moved and refactored PinType and PinDirection --- .../hal_core/netlist/gate_library/gate_type.h | 102 +++--- include/hal_core/utilities/enums.h | 28 +- .../src/plugin_boolean_influence.cpp | 2 +- .../src/pre_processing/pre_processing.cpp | 8 +- .../include/hgl_parser/hgl_parser.h | 6 +- plugins/hgl_parser/src/hgl_parser.cpp | 61 +--- plugins/hgl_parser/test/hgl_parser.cpp | 94 ++--- .../include/hgl_writer/hgl_writer.h | 2 - plugins/hgl_writer/src/hgl_writer.cpp | 64 +--- plugins/hgl_writer/test/hgl_writer.cpp | 56 +-- .../include/liberty_parser/liberty_parser.h | 14 +- plugins/liberty_parser/src/liberty_parser.cpp | 80 ++--- .../liberty_parser/test/liberty_parser.cpp | 16 +- .../src/netlist_simulator.cpp | 22 +- plugins/solve_fsm/src/plugin_solve_fsm.cpp | 335 +++++++++++------- .../hdl_parser_template.h | 6 +- src/netlist/gate.cpp | 4 +- src/netlist/gate_library/gate_type.cpp | 54 +-- src/netlist/netlist_utils.cpp | 2 +- src/python_bindings/bindings/gate_type.cpp | 53 ++- tests/netlist/gate.cpp | 4 +- tests/netlist/gate_type.cpp | 308 ++++++++-------- tests/netlist/netlist_utils.cpp | 20 +- 23 files changed, 684 insertions(+), 657 deletions(-) diff --git a/include/hal_core/netlist/gate_library/gate_type.h b/include/hal_core/netlist/gate_library/gate_type.h index 54754701060..9403d348491 100644 --- a/include/hal_core/netlist/gate_library/gate_type.h +++ b/include/hal_core/netlist/gate_library/gate_type.h @@ -53,9 +53,51 @@ namespace hal dsp, /**< DSP gate type. **/ mux, /**< MUX gate type. **/ buffer, /**< Buffer gate type. **/ - carry, /**< Carry gate type. **/ - invalid /**< Invalid property. **/ + carry /**< Carry gate type. **/ }; + + template<> + std::vector EnumStrings::data; + + /** + * Defines the direction of a pin. + */ + enum class PinDirection + { + none, /**< Invalid pin. **/ + input, /**< Input pin. **/ + output, /**< Output pin. **/ + inout, /**< Inout pin. **/ + internal /**< Internal pin. **/ + }; + + template<> + std::vector EnumStrings::data; + + /** + * Defines the type of a pin. + */ + enum class PinType + { + none, /**< Default pin. **/ + power, /**< Power pin. **/ + ground, /**< Ground pin. **/ + lut, /**< Pin that generates output from LUT initialization string. **/ + state, /**< Pin that generates output from internal state. **/ + neg_state, /**< Pin that generates output from negated internal state. **/ + clock, /**< Clock pin. **/ + enable, /**< Enable pin. **/ + set, /**< Set/preset pin. **/ + reset, /**< Reset/clear pin. **/ + data, /**< Data pin. **/ + address, /**< Address pin. **/ + io_pad, /**< IO pad pin. **/ + select /**< Select pin. **/ + }; + + template<> + std::vector EnumStrings::data; + /** * A gate type contains information about its internals such as input and output pins as well as its Boolean functions. * @@ -64,50 +106,17 @@ namespace hal class NETLIST_API GateType { public: - /** - * Defines the direction of a pin. - */ - enum class PinDirection - { - none, /**< Invalid pin. **/ - input, /**< Input pin. **/ - output, /**< Output pin. **/ - inout, /**< Inout pin. **/ - internal /**< Internal pin. **/ - }; - - /** - * Defines the type of a pin. - */ - enum class PinType - { - none, /**< Default pin. **/ - power, /**< Power pin. **/ - ground, /**< Ground pin. **/ - lut, /**< Pin that generates output from LUT initialization string. **/ - state, /**< Pin that generates output from internal state. **/ - neg_state, /**< Pin that generates output from negated internal state. **/ - clock, /**< Clock pin. **/ - enable, /**< Enable pin. **/ - set, /**< Set/preset pin. **/ - reset, /**< Reset/clear pin. **/ - data, /**< Data pin. **/ - address, /**< Address pin. **/ - io_pad, /**< IO pad pin. **/ - select /**< Select pin. **/ - }; - /** * Defines the behavior of the gate type in case both clear and preset are active at the same time. */ enum class ClearPresetBehavior { - L, /**< Set the internal state to \p 0. **/ - H, /**< Set the internal state to \p 1. **/ - N, /**< Do not change the internal state. **/ - T, /**< Toggle, i.e., invert the internal state. **/ - X, /**< Set the internal state to \p X. **/ - invalid /**< Invalid behavior, used by default. **/ + L, /**< Set the internal state to \p 0. **/ + H, /**< Set the internal state to \p 1. **/ + N, /**< Do not change the internal state. **/ + T, /**< Toggle, i.e., invert the internal state. **/ + X, /**< Set the internal state to \p X. **/ + undef /**< Invalid behavior, used by default. **/ }; /** @@ -431,10 +440,6 @@ namespace hal std::string m_name; std::set m_properties; - // enum to string - static const std::unordered_map m_pin_direction_to_string; - static const std::unordered_map m_pin_type_to_string; - // pins std::vector m_pins; std::unordered_set m_pins_set; @@ -455,7 +460,7 @@ namespace hal std::unordered_map m_functions; // sequential and LUT stuff - std::pair m_clear_preset_behavior = {ClearPresetBehavior::invalid, ClearPresetBehavior::invalid}; + std::pair m_clear_preset_behavior = {ClearPresetBehavior::undef, ClearPresetBehavior::undef}; std::string m_config_data_category = ""; std::string m_config_data_identifier = ""; bool m_ascending = true; @@ -466,11 +471,6 @@ namespace hal GateType& operator=(const GateType&) = delete; }; - template<> - std::vector EnumStrings::data; - template<> std::vector EnumStrings::data; - - } // namespace hal diff --git a/include/hal_core/utilities/enums.h b/include/hal_core/utilities/enums.h index 179e5f4d7e0..f58e03235fc 100644 --- a/include/hal_core/utilities/enums.h +++ b/include/hal_core/utilities/enums.h @@ -28,14 +28,14 @@ namespace hal auto index = static_cast(e); if (index >= EnumStrings::data.size()) { - throw std::runtime_error("no string for enum with value '" + std::to_string(index) + "'"); + throw std::runtime_error("no string for enum with value '" + std::to_string(index) + "'."); } return EnumStrings::data.at(index); } /** * Translates a string into an enum value if possible. - * Assumes the last enum entry to represent an invalid state, as it defaults to this value. + * Throws an exception if no matching enum value is found. * * @param[in] str - The string. * @returns The enum value. @@ -51,7 +51,29 @@ namespace hal } } - return static_cast(EnumStrings::data.size() - 1); + throw std::runtime_error("no enum value for string `" + str + "` available."); + } + + /** + * Translates a string into an enum value if possible. + * Defaults to the given default value if no matching enum value is found. + * + * @param[in] str - The string. + * @param[in] default_val - The default value. + * @returns The enum value. + */ + template::value, T>::type> + T enum_from_string(const std::string& str, const T default_val) noexcept + { + for (size_t i = 0; i < EnumStrings::data.size(); i++) + { + if (EnumStrings::data.at(i) == str) + { + return static_cast(i); + } + } + + return default_val; } /** diff --git a/plugins/boolean_influence/src/plugin_boolean_influence.cpp b/plugins/boolean_influence/src/plugin_boolean_influence.cpp index 820916adb08..8fbe0f4395f 100644 --- a/plugins/boolean_influence/src/plugin_boolean_influence.cpp +++ b/plugins/boolean_influence/src/plugin_boolean_influence.cpp @@ -32,7 +32,7 @@ namespace hal } // Check for the data port pin - std::unordered_set d_ports = gate->get_type()->get_pins_of_type(GateType::PinType::data); + std::unordered_set d_ports = gate->get_type()->get_pins_of_type(PinType::data); if (d_ports.size() != 1) { log_error("boolean_influence", "Can only handle flip flops with exactly 1 data port, but found {}.", d_ports.size()); diff --git a/plugins/dataflow_analysis/src/pre_processing/pre_processing.cpp b/plugins/dataflow_analysis/src/pre_processing/pre_processing.cpp index 5b8f31873df..b0f497058b0 100644 --- a/plugins/dataflow_analysis/src/pre_processing/pre_processing.cpp +++ b/plugins/dataflow_analysis/src/pre_processing/pre_processing.cpp @@ -182,25 +182,25 @@ namespace hal auto id = sg->get_id(); sg->get_name(); - for (auto net : netlist_utils::get_nets_at_pins(sg, sg->get_type()->get_pins_of_type(GateType::PinType::clock), true)) + for (auto net : netlist_utils::get_nets_at_pins(sg, sg->get_type()->get_pins_of_type(PinType::clock), true)) { netlist_abstr.gate_to_clock_signals[id].insert(net->get_id()); fingerprint.push_back(net->get_id()); } - for (auto net : netlist_utils::get_nets_at_pins(sg, sg->get_type()->get_pins_of_type(GateType::PinType::enable), true)) + for (auto net : netlist_utils::get_nets_at_pins(sg, sg->get_type()->get_pins_of_type(PinType::enable), true)) { netlist_abstr.gate_to_enable_signals[id].insert(net->get_id()); fingerprint.push_back(net->get_id()); } - for (auto net : netlist_utils::get_nets_at_pins(sg, sg->get_type()->get_pins_of_type(GateType::PinType::reset), true)) + for (auto net : netlist_utils::get_nets_at_pins(sg, sg->get_type()->get_pins_of_type(PinType::reset), true)) { netlist_abstr.gate_to_reset_signals[id].insert(net->get_id()); fingerprint.push_back(net->get_id()); } - for (auto net : netlist_utils::get_nets_at_pins(sg, sg->get_type()->get_pins_of_type(GateType::PinType::set), true)) + for (auto net : netlist_utils::get_nets_at_pins(sg, sg->get_type()->get_pins_of_type(PinType::set), true)) { netlist_abstr.gate_to_set_signals[id].insert(net->get_id()); fingerprint.push_back(net->get_id()); diff --git a/plugins/hgl_parser/include/hgl_parser/hgl_parser.h b/plugins/hgl_parser/include/hgl_parser/hgl_parser.h index cae9eea1db9..6777c1b0090 100644 --- a/plugins/hgl_parser/include/hgl_parser/hgl_parser.h +++ b/plugins/hgl_parser/include/hgl_parser/hgl_parser.h @@ -56,8 +56,8 @@ namespace hal struct PinCtx { std::vector pins; - std::unordered_map pin_to_type; - std::unordered_map pin_to_direction; + std::unordered_map pin_to_type; + std::unordered_map pin_to_direction; std::unordered_map boolean_functions; }; @@ -66,8 +66,6 @@ namespace hal std::set m_cell_names; - static const std::unordered_map m_string_to_pin_type; - bool parse_gate_library(const rapidjson::Document& document); bool parse_gate_type(const rapidjson::Value& gate_type); bool parse_pin(PinCtx& pin_ctx, const rapidjson::Value& pin, const std::string& gt_name); diff --git a/plugins/hgl_parser/src/hgl_parser.cpp b/plugins/hgl_parser/src/hgl_parser.cpp index 60f4f987f2c..ce0dd2f0fb7 100644 --- a/plugins/hgl_parser/src/hgl_parser.cpp +++ b/plugins/hgl_parser/src/hgl_parser.cpp @@ -7,21 +7,6 @@ namespace hal { - const std::unordered_map HGLParser::m_string_to_pin_type = {{"none", GateType::PinType::none}, - {"power", GateType::PinType::power}, - {"ground", GateType::PinType::ground}, - {"lut", GateType::PinType::lut}, - {"state", GateType::PinType::state}, - {"neg_state", GateType::PinType::neg_state}, - {"clock", GateType::PinType::clock}, - {"enable", GateType::PinType::enable}, - {"set", GateType::PinType::set}, - {"reset", GateType::PinType::reset}, - {"data", GateType::PinType::data}, - {"address", GateType::PinType::address}, - {"io_pad", GateType::PinType::io_pad}, - {"select", GateType::PinType::select}}; - std::unique_ptr HGLParser::parse(const std::filesystem::path& file_path) { m_path = file_path; @@ -97,11 +82,12 @@ namespace hal { for (const auto& base_type : gate_type["types"].GetArray()) { - if (auto property = enum_from_string(base_type.GetString()); property != GateTypeProperty::invalid) + try { + GateTypeProperty property = enum_from_string(base_type.GetString()); properties.insert(property); } - else + catch (const std::runtime_error&) { log_error("hgl_parser", "invalid base type '{}' given for gate type '{}'.", base_type.GetString(), name); return false; @@ -219,27 +205,12 @@ namespace hal } std::string direction = pin["direction"].GetString(); - if (direction == "input") - { - pin_ctx.pins.push_back(name); - pin_ctx.pin_to_direction[name] = GateType::PinDirection::input; - } - else if (direction == "output") - { - pin_ctx.pins.push_back(name); - pin_ctx.pin_to_direction[name] = GateType::PinDirection::output; - } - else if (direction == "inout") - { - pin_ctx.pins.push_back(name); - pin_ctx.pin_to_direction[name] = GateType::PinDirection::inout; - } - else if (direction == "internal") + try { + pin_ctx.pin_to_direction[name] = enum_from_string(direction); pin_ctx.pins.push_back(name); - pin_ctx.pin_to_direction[name] = GateType::PinDirection::internal; } - else + catch (const std::runtime_error&) { log_warning("hgl_parser", "invalid direction '{}' given for pin '{}' of gate type '{}'.", direction, name, gt_name); return false; @@ -263,11 +234,11 @@ namespace hal if (pin.HasMember("type") && pin["type"].IsString()) { std::string type_str = pin["type"].GetString(); - if (auto it = m_string_to_pin_type.find(type_str); it != m_string_to_pin_type.end()) + try { - pin_ctx.pin_to_type[name] = it->second; + pin_ctx.pin_to_type[name] = enum_from_string(type_str); } - else + catch (const std::runtime_error&) { log_warning("hgl_parser", "invalid type '{}' given for pin '{}' of gate type '{}'.", type_str, name, gt_name); return false; @@ -275,7 +246,7 @@ namespace hal } else { - pin_ctx.pin_to_type[name] = GateType::PinType::none; + pin_ctx.pin_to_type[name] = PinType::none; } return true; @@ -376,7 +347,8 @@ namespace hal { GateType::ClearPresetBehavior cp1, cp2; - if (const auto behav = enum_from_string(ff_config["state_clear_preset"].GetString()); behav != GateType::ClearPresetBehavior::invalid) + if (const auto behav = enum_from_string(ff_config["state_clear_preset"].GetString(), GateType::ClearPresetBehavior::undef); + behav != GateType::ClearPresetBehavior::undef) { cp1 = behav; } @@ -386,7 +358,8 @@ namespace hal return false; } - if (const auto behav = enum_from_string(ff_config["neg_state_clear_preset"].GetString()); behav != GateType::ClearPresetBehavior::invalid) + if (const auto behav = enum_from_string(ff_config["neg_state_clear_preset"].GetString(), GateType::ClearPresetBehavior::undef); + behav != GateType::ClearPresetBehavior::undef) { cp2 = behav; } @@ -446,7 +419,8 @@ namespace hal { GateType::ClearPresetBehavior cp1, cp2; - if (const auto behav = enum_from_string(latch_config["state_clear_preset"].GetString()); behav != GateType::ClearPresetBehavior::invalid) + if (const auto behav = enum_from_string(latch_config["state_clear_preset"].GetString(), GateType::ClearPresetBehavior::undef); + behav != GateType::ClearPresetBehavior::undef) { cp1 = behav; } @@ -456,7 +430,8 @@ namespace hal return false; } - if (const auto behav = enum_from_string(latch_config["neg_state_clear_preset"].GetString()); behav != GateType::ClearPresetBehavior::invalid) + if (const auto behav = enum_from_string(latch_config["neg_state_clear_preset"].GetString(), GateType::ClearPresetBehavior::undef); + behav != GateType::ClearPresetBehavior::undef) { cp2 = behav; } diff --git a/plugins/hgl_parser/test/hgl_parser.cpp b/plugins/hgl_parser/test/hgl_parser.cpp index b024df4d564..178c9ac2e4c 100644 --- a/plugins/hgl_parser/test/hgl_parser.cpp +++ b/plugins/hgl_parser/test/hgl_parser.cpp @@ -55,11 +55,11 @@ namespace hal EXPECT_EQ(gt->get_output_pins(), std::vector({"B", "O"})); // pin types - EXPECT_EQ(gt->get_pin_type("VDD"), GateType::PinType::power); - EXPECT_EQ(gt->get_pin_type("GND"), GateType::PinType::ground); - EXPECT_EQ(gt->get_pin_type("A"), GateType::PinType::none); - EXPECT_EQ(gt->get_pin_type("B"), GateType::PinType::none); - EXPECT_EQ(gt->get_pin_type("O"), GateType::PinType::none); + EXPECT_EQ(gt->get_pin_type("VDD"), PinType::power); + EXPECT_EQ(gt->get_pin_type("GND"), PinType::ground); + EXPECT_EQ(gt->get_pin_type("A"), PinType::none); + EXPECT_EQ(gt->get_pin_type("B"), PinType::none); + EXPECT_EQ(gt->get_pin_type("O"), PinType::none); // pin groups EXPECT_TRUE(gt->get_pin_groups().empty()); @@ -75,7 +75,7 @@ namespace hal ASSERT_EQ(functions.at("O_tristate"), BooleanFunction::from_string("!A & !B")); // clear-preset behavior - ASSERT_EQ(gt->get_clear_preset_behavior(), std::pair(GateType::ClearPresetBehavior::invalid, GateType::ClearPresetBehavior::invalid)); + ASSERT_EQ(gt->get_clear_preset_behavior(), std::pair(GateType::ClearPresetBehavior::undef, GateType::ClearPresetBehavior::undef)); // config data and init string ASSERT_EQ(gt->get_config_data_category(), ""); @@ -98,15 +98,15 @@ namespace hal EXPECT_EQ(gt->get_output_pins(), std::vector({"B(0)", "B(1)", "C(0)", "C(1)", "O"})); // pin types - EXPECT_EQ(gt->get_pin_type("VDD"), GateType::PinType::power); - EXPECT_EQ(gt->get_pin_type("GND"), GateType::PinType::ground); - EXPECT_EQ(gt->get_pin_type("A(0)"), GateType::PinType::none); - EXPECT_EQ(gt->get_pin_type("A(1)"), GateType::PinType::none); - EXPECT_EQ(gt->get_pin_type("B(0)"), GateType::PinType::none); - EXPECT_EQ(gt->get_pin_type("B(1)"), GateType::PinType::none); - EXPECT_EQ(gt->get_pin_type("C(0)"), GateType::PinType::none); - EXPECT_EQ(gt->get_pin_type("C(1)"), GateType::PinType::none); - EXPECT_EQ(gt->get_pin_type("O"), GateType::PinType::none); + EXPECT_EQ(gt->get_pin_type("VDD"), PinType::power); + EXPECT_EQ(gt->get_pin_type("GND"), PinType::ground); + EXPECT_EQ(gt->get_pin_type("A(0)"), PinType::none); + EXPECT_EQ(gt->get_pin_type("A(1)"), PinType::none); + EXPECT_EQ(gt->get_pin_type("B(0)"), PinType::none); + EXPECT_EQ(gt->get_pin_type("B(1)"), PinType::none); + EXPECT_EQ(gt->get_pin_type("C(0)"), PinType::none); + EXPECT_EQ(gt->get_pin_type("C(1)"), PinType::none); + EXPECT_EQ(gt->get_pin_type("O"), PinType::none); // pin groups std::unordered_map> expected_groups({{"A", {{0, "A(0)"}, {1, "A(1)"}}}, {"B", {{0, "B(0)"}, {1, "B(1)"}}}, {"C", {{0, "C(0)"}, {1, "C(1)"}}}}); @@ -123,7 +123,7 @@ namespace hal ASSERT_EQ(functions.at("O_tristate"), BooleanFunction::from_string("!A(1) & !B(1)", std::vector({"A(1)", "B(1)"}))); // clear-preset behavior - ASSERT_EQ(gt->get_clear_preset_behavior(), std::pair(GateType::ClearPresetBehavior::invalid, GateType::ClearPresetBehavior::invalid)); + ASSERT_EQ(gt->get_clear_preset_behavior(), std::pair(GateType::ClearPresetBehavior::undef, GateType::ClearPresetBehavior::undef)); // config data and init string ASSERT_EQ(gt->get_config_data_category(), ""); @@ -146,9 +146,9 @@ namespace hal EXPECT_EQ(gt->get_output_pins(), std::vector({"O"})); // pin types - EXPECT_EQ(gt->get_pin_type("I1"), GateType::PinType::none); - EXPECT_EQ(gt->get_pin_type("I2"), GateType::PinType::none); - EXPECT_EQ(gt->get_pin_type("O"), GateType::PinType::lut); + EXPECT_EQ(gt->get_pin_type("I1"), PinType::none); + EXPECT_EQ(gt->get_pin_type("I2"), PinType::none); + EXPECT_EQ(gt->get_pin_type("O"), PinType::lut); // pin groups EXPECT_TRUE(gt->get_pin_groups().empty()); @@ -158,7 +158,7 @@ namespace hal ASSERT_TRUE(functions.empty()); // clear-preset behavior - ASSERT_EQ(gt->get_clear_preset_behavior(), std::pair(GateType::ClearPresetBehavior::invalid, GateType::ClearPresetBehavior::invalid)); + ASSERT_EQ(gt->get_clear_preset_behavior(), std::pair(GateType::ClearPresetBehavior::undef, GateType::ClearPresetBehavior::undef)); // config data and init string ASSERT_EQ(gt->get_config_data_category(), "generic"); @@ -181,9 +181,9 @@ namespace hal EXPECT_EQ(gt->get_output_pins(), std::vector({"O"})); // pin types - EXPECT_EQ(gt->get_pin_type("I1"), GateType::PinType::none); - EXPECT_EQ(gt->get_pin_type("I2"), GateType::PinType::none); - EXPECT_EQ(gt->get_pin_type("O"), GateType::PinType::lut); + EXPECT_EQ(gt->get_pin_type("I1"), PinType::none); + EXPECT_EQ(gt->get_pin_type("I2"), PinType::none); + EXPECT_EQ(gt->get_pin_type("O"), PinType::lut); // pin groups EXPECT_TRUE(gt->get_pin_groups().empty()); @@ -193,7 +193,7 @@ namespace hal ASSERT_TRUE(functions.empty()); // clear-preset behavior - ASSERT_EQ(gt->get_clear_preset_behavior(), std::pair(GateType::ClearPresetBehavior::invalid, GateType::ClearPresetBehavior::invalid)); + ASSERT_EQ(gt->get_clear_preset_behavior(), std::pair(GateType::ClearPresetBehavior::undef, GateType::ClearPresetBehavior::undef)); // config data and init string ASSERT_EQ(gt->get_config_data_category(), "generic"); @@ -216,13 +216,13 @@ namespace hal EXPECT_EQ(gt->get_output_pins(), std::vector({"Q", "QN"})); // pin types - EXPECT_EQ(gt->get_pin_type("CLK"), GateType::PinType::clock); - EXPECT_EQ(gt->get_pin_type("D"), GateType::PinType::data); - EXPECT_EQ(gt->get_pin_type("EN"), GateType::PinType::enable); - EXPECT_EQ(gt->get_pin_type("R"), GateType::PinType::reset); - EXPECT_EQ(gt->get_pin_type("S"), GateType::PinType::set); - EXPECT_EQ(gt->get_pin_type("Q"), GateType::PinType::state); - EXPECT_EQ(gt->get_pin_type("QN"), GateType::PinType::neg_state); + EXPECT_EQ(gt->get_pin_type("CLK"), PinType::clock); + EXPECT_EQ(gt->get_pin_type("D"), PinType::data); + EXPECT_EQ(gt->get_pin_type("EN"), PinType::enable); + EXPECT_EQ(gt->get_pin_type("R"), PinType::reset); + EXPECT_EQ(gt->get_pin_type("S"), PinType::set); + EXPECT_EQ(gt->get_pin_type("Q"), PinType::state); + EXPECT_EQ(gt->get_pin_type("QN"), PinType::neg_state); // pin groups EXPECT_TRUE(gt->get_pin_groups().empty()); @@ -263,12 +263,12 @@ namespace hal EXPECT_EQ(gt->get_output_pins(), std::vector({"Q", "QN"})); // pin types - EXPECT_EQ(gt->get_pin_type("D"), GateType::PinType::data); - EXPECT_EQ(gt->get_pin_type("EN"), GateType::PinType::enable); - EXPECT_EQ(gt->get_pin_type("R"), GateType::PinType::reset); - EXPECT_EQ(gt->get_pin_type("S"), GateType::PinType::set); - EXPECT_EQ(gt->get_pin_type("Q"), GateType::PinType::state); - EXPECT_EQ(gt->get_pin_type("QN"), GateType::PinType::neg_state); + EXPECT_EQ(gt->get_pin_type("D"), PinType::data); + EXPECT_EQ(gt->get_pin_type("EN"), PinType::enable); + EXPECT_EQ(gt->get_pin_type("R"), PinType::reset); + EXPECT_EQ(gt->get_pin_type("S"), PinType::set); + EXPECT_EQ(gt->get_pin_type("Q"), PinType::state); + EXPECT_EQ(gt->get_pin_type("QN"), PinType::neg_state); // pin groups EXPECT_TRUE(gt->get_pin_groups().empty()); @@ -309,15 +309,15 @@ namespace hal EXPECT_EQ(gt->get_output_pins(), std::vector({"DO(0)", "DO(1)", "DO(2)"})); // pin types - EXPECT_EQ(gt->get_pin_type("DI(0)"), GateType::PinType::data); - EXPECT_EQ(gt->get_pin_type("DI(1)"), GateType::PinType::data); - EXPECT_EQ(gt->get_pin_type("DI(2)"), GateType::PinType::data); - EXPECT_EQ(gt->get_pin_type("A(0)"), GateType::PinType::address); - EXPECT_EQ(gt->get_pin_type("A(1)"), GateType::PinType::address); - EXPECT_EQ(gt->get_pin_type("A(2)"), GateType::PinType::address); - EXPECT_EQ(gt->get_pin_type("DO(0)"), GateType::PinType::data); - EXPECT_EQ(gt->get_pin_type("DO(1)"), GateType::PinType::data); - EXPECT_EQ(gt->get_pin_type("DO(2)"), GateType::PinType::data); + EXPECT_EQ(gt->get_pin_type("DI(0)"), PinType::data); + EXPECT_EQ(gt->get_pin_type("DI(1)"), PinType::data); + EXPECT_EQ(gt->get_pin_type("DI(2)"), PinType::data); + EXPECT_EQ(gt->get_pin_type("A(0)"), PinType::address); + EXPECT_EQ(gt->get_pin_type("A(1)"), PinType::address); + EXPECT_EQ(gt->get_pin_type("A(2)"), PinType::address); + EXPECT_EQ(gt->get_pin_type("DO(0)"), PinType::data); + EXPECT_EQ(gt->get_pin_type("DO(1)"), PinType::data); + EXPECT_EQ(gt->get_pin_type("DO(2)"), PinType::data); // pin groups std::unordered_map> expected_groups({{"DI", {{0, "DI(0)"}, {1, "DI(1)"}, {2, "DI(2)"}}}, {"A", {{0, "A(0)"}, {1, "A(1)"}, {2, "A(2)"}}}, {"DO", {{0, "DO(0)"}, {1, "DO(1)"}, {2, "DO(2)"}}}}); @@ -328,7 +328,7 @@ namespace hal ASSERT_TRUE(functions.empty()); // clear-preset behavior - ASSERT_EQ(gt->get_clear_preset_behavior(), std::pair(GateType::ClearPresetBehavior::invalid, GateType::ClearPresetBehavior::invalid)); + ASSERT_EQ(gt->get_clear_preset_behavior(), std::pair(GateType::ClearPresetBehavior::undef, GateType::ClearPresetBehavior::undef)); // config data and init string ASSERT_EQ(gt->get_config_data_category(), ""); diff --git a/plugins/hgl_writer/include/hgl_writer/hgl_writer.h b/plugins/hgl_writer/include/hgl_writer/hgl_writer.h index 9d3f2c077ff..78eaf03aba5 100644 --- a/plugins/hgl_writer/include/hgl_writer/hgl_writer.h +++ b/plugins/hgl_writer/include/hgl_writer/hgl_writer.h @@ -74,8 +74,6 @@ namespace hal std::map index_to_pin; }; - static const std::unordered_map m_pin_type_to_string; - bool write_gate_library(rapidjson::Document& document, const GateLibrary* gate_lib); std::vector get_pins(GateType* gt, const std::unordered_map& functions); diff --git a/plugins/hgl_writer/src/hgl_writer.cpp b/plugins/hgl_writer/src/hgl_writer.cpp index 5b4bba98767..ae9483288a2 100644 --- a/plugins/hgl_writer/src/hgl_writer.cpp +++ b/plugins/hgl_writer/src/hgl_writer.cpp @@ -10,21 +10,6 @@ namespace hal { - const std::unordered_map HGLWriter::m_pin_type_to_string = {{GateType::PinType::none, "none"}, - {GateType::PinType::power, "power"}, - {GateType::PinType::ground, "ground"}, - {GateType::PinType::lut, "lut"}, - {GateType::PinType::state, "state"}, - {GateType::PinType::neg_state, "neg_state"}, - {GateType::PinType::clock, "clock"}, - {GateType::PinType::enable, "enable"}, - {GateType::PinType::set, "set"}, - {GateType::PinType::reset, "reset"}, - {GateType::PinType::data, "data"}, - {GateType::PinType::address, "address"}, - {GateType::PinType::io_pad, "io_pad"}, - {GateType::PinType::select, "select"}}; - bool HGLWriter::write(const GateLibrary* gate_lib, const std::filesystem::path& file_path) { if (gate_lib == nullptr) @@ -95,11 +80,8 @@ namespace hal for (const auto& property : properties) { - if (property != GateTypeProperty::invalid) - { - std::string bt_str = enum_to_string(property); - bts.PushBack(rapidjson::Value{}.SetString(bt_str.c_str(), bt_str.length(), allocator), allocator); - } + std::string bt_str = enum_to_string(property); + bts.PushBack(rapidjson::Value{}.SetString(bt_str.c_str(), bt_str.length(), allocator), allocator); } cell.AddMember("types", bts, allocator); @@ -154,11 +136,11 @@ namespace hal } std::pair cp_behav = gt->get_clear_preset_behavior(); - if (cp_behav.first != GateType::ClearPresetBehavior::invalid) + if (cp_behav.first != GateType::ClearPresetBehavior::undef) { ff_config.AddMember("state_clear_preset", enum_to_string(cp_behav.first), allocator); } - if (cp_behav.second != GateType::ClearPresetBehavior::invalid) + if (cp_behav.second != GateType::ClearPresetBehavior::undef) { ff_config.AddMember("neg_state_clear_preset", enum_to_string(cp_behav.second), allocator); } @@ -188,11 +170,11 @@ namespace hal } std::pair cp_behav = gt->get_clear_preset_behavior(); - if (cp_behav.first != GateType::ClearPresetBehavior::invalid) + if (cp_behav.first != GateType::ClearPresetBehavior::undef) { latch_config.AddMember("state_clear_preset", enum_to_string(cp_behav.first), allocator); } - if (cp_behav.second != GateType::ClearPresetBehavior::invalid) + if (cp_behav.second != GateType::ClearPresetBehavior::undef) { latch_config.AddMember("neg_state_clear_preset", enum_to_string(cp_behav.second), allocator); } @@ -271,37 +253,29 @@ namespace hal std::vector HGLWriter::get_pins(GateType* gt, const std::unordered_map& functions) { std::vector res; - const std::vector& pins = gt->get_pins(); - const std::unordered_map& pin_to_direction = gt->get_pin_directions(); - const std::unordered_map& pin_to_type = gt->get_pin_types(); + const std::vector& pins = gt->get_pins(); + const std::unordered_map& pin_to_direction = gt->get_pin_directions(); + const std::unordered_map& pin_to_type = gt->get_pin_types(); for (const auto& pin : pins) { PinCtx res_pin; res_pin.name = pin; - if (pin_to_type.at(pin) != GateType::PinType::none) + if (pin_to_type.at(pin) != PinType::none) + { + res_pin.type = enum_to_string(pin_to_type.at(pin)); + } + + if (pin_to_direction.at(pin) != PinDirection::none) { - res_pin.type = m_pin_type_to_string.at(pin_to_type.at(pin)); + res_pin.direction = enum_to_string(pin_to_direction.at(pin)); } - switch (pin_to_direction.at(pin)) + else { - case GateType::PinDirection::none: - continue; - case GateType::PinDirection::input: - res_pin.direction = "input"; - break; - case GateType::PinDirection::output: - res_pin.direction = "output"; - break; - case GateType::PinDirection::inout: - res_pin.direction = "inout"; - break; - case GateType::PinDirection::internal: - res_pin.direction = "internal"; - break; + log_error("hgl_writer", "invalid pin type 'none' for pin '{}' of gate type '{}' with ID {}.", pin, gt->get_name(), gt->get_id()); } - if (pin_to_direction.at(pin) == GateType::PinDirection::output || pin_to_direction.at(pin) == GateType::PinDirection::inout) + if (pin_to_direction.at(pin) == PinDirection::output || pin_to_direction.at(pin) == PinDirection::inout) { if (const auto it = functions.find(pin); it != functions.end()) { diff --git a/plugins/hgl_writer/test/hgl_writer.cpp b/plugins/hgl_writer/test/hgl_writer.cpp index 53891bce4ef..443f01c3ab9 100644 --- a/plugins/hgl_writer/test/hgl_writer.cpp +++ b/plugins/hgl_writer/test/hgl_writer.cpp @@ -17,8 +17,8 @@ namespace hal gt->add_input_pins({"VDD", "GND", "A", "B"}); gt->add_output_pins({"B", "O"}); - gt->assign_pin_type("VDD", GateType::PinType::power); - gt->assign_pin_type("GND", GateType::PinType::ground); + gt->assign_pin_type("VDD", PinType::power); + gt->assign_pin_type("GND", PinType::ground); gt->add_boolean_function("O", BooleanFunction::from_string("A & B")); gt->add_boolean_function("O_undefined", BooleanFunction::from_string("!A & B")); @@ -35,8 +35,8 @@ namespace hal gt->assign_pin_group("B", {{0, "B(0)"}, {1, "B(1)"}}); gt->assign_pin_group("C", {{0, "C(0)"}, {1, "C(1)"}}); - gt->assign_pin_type("VDD", GateType::PinType::power); - gt->assign_pin_type("GND", GateType::PinType::ground); + gt->assign_pin_type("VDD", PinType::power); + gt->assign_pin_type("GND", PinType::ground); gt->add_boolean_function("O", BooleanFunction::from_string("A(1) & B(0)", {"A(1)", "B(0)"})); gt->add_boolean_function("O_undefined", BooleanFunction::from_string("!A(0) & B(0)", {"A(0)", "B(0)"})); @@ -49,7 +49,7 @@ namespace hal gt->add_input_pins({"I1", "I2"}); gt->add_output_pins({"O"}); - gt->assign_pin_type("O", GateType::PinType::lut); + gt->assign_pin_type("O", PinType::lut); gt->set_config_data_category("generic"); gt->set_config_data_identifier("INIT"); @@ -62,7 +62,7 @@ namespace hal gt->add_input_pins({"I1", "I2"}); gt->add_output_pins({"O"}); - gt->assign_pin_type("O", GateType::PinType::lut); + gt->assign_pin_type("O", PinType::lut); gt->set_config_data_category("generic"); gt->set_config_data_identifier("INIT"); @@ -75,13 +75,13 @@ namespace hal gt->add_input_pins({"CLK", "D", "EN", "R", "S"}); gt->add_output_pins({"Q", "QN"}); - gt->assign_pin_type("CLK", GateType::PinType::clock); - gt->assign_pin_type("D", GateType::PinType::data); - gt->assign_pin_type("EN", GateType::PinType::enable); - gt->assign_pin_type("R", GateType::PinType::reset); - gt->assign_pin_type("S", GateType::PinType::set); - gt->assign_pin_type("Q", GateType::PinType::state); - gt->assign_pin_type("QN", GateType::PinType::neg_state); + gt->assign_pin_type("CLK", PinType::clock); + gt->assign_pin_type("D", PinType::data); + gt->assign_pin_type("EN", PinType::enable); + gt->assign_pin_type("R", PinType::reset); + gt->assign_pin_type("S", PinType::set); + gt->assign_pin_type("Q", PinType::state); + gt->assign_pin_type("QN", PinType::neg_state); gt->add_boolean_function("next_state", BooleanFunction::from_string("D")); gt->add_boolean_function("clock", BooleanFunction::from_string("CLK & EN")); @@ -99,12 +99,12 @@ namespace hal gt->add_input_pins({"D", "EN", "R", "S"}); gt->add_output_pins({"Q", "QN"}); - gt->assign_pin_type("D", GateType::PinType::data); - gt->assign_pin_type("EN", GateType::PinType::enable); - gt->assign_pin_type("R", GateType::PinType::reset); - gt->assign_pin_type("S", GateType::PinType::set); - gt->assign_pin_type("Q", GateType::PinType::state); - gt->assign_pin_type("QN", GateType::PinType::neg_state); + gt->assign_pin_type("D", PinType::data); + gt->assign_pin_type("EN", PinType::enable); + gt->assign_pin_type("R", PinType::reset); + gt->assign_pin_type("S", PinType::set); + gt->assign_pin_type("Q", PinType::state); + gt->assign_pin_type("QN", PinType::neg_state); gt->add_boolean_function("data", BooleanFunction::from_string("D")); gt->add_boolean_function("enable", BooleanFunction::from_string("EN")); @@ -124,15 +124,15 @@ namespace hal gt->assign_pin_group("A", {{0, "A(0)"}, {1, "A(1)"}, {2, "A(2)"}}); gt->assign_pin_group("DO", {{0, "DO(0)"}, {1, "DO(1)"}, {2, "DO(2)"}}); - gt->assign_pin_type("DI(0)", GateType::PinType::data); - gt->assign_pin_type("DI(1)", GateType::PinType::data); - gt->assign_pin_type("DI(2)", GateType::PinType::data); - gt->assign_pin_type("A(0)", GateType::PinType::address); - gt->assign_pin_type("A(1)", GateType::PinType::address); - gt->assign_pin_type("A(2)", GateType::PinType::address); - gt->assign_pin_type("DO(0)", GateType::PinType::data); - gt->assign_pin_type("DO(1)", GateType::PinType::data); - gt->assign_pin_type("DO(2)", GateType::PinType::data); + gt->assign_pin_type("DI(0)", PinType::data); + gt->assign_pin_type("DI(1)", PinType::data); + gt->assign_pin_type("DI(2)", PinType::data); + gt->assign_pin_type("A(0)", PinType::address); + gt->assign_pin_type("A(1)", PinType::address); + gt->assign_pin_type("A(2)", PinType::address); + gt->assign_pin_type("DO(0)", PinType::data); + gt->assign_pin_type("DO(1)", PinType::data); + gt->assign_pin_type("DO(2)", PinType::data); } return gl; diff --git a/plugins/liberty_parser/include/liberty_parser/liberty_parser.h b/plugins/liberty_parser/include/liberty_parser/liberty_parser.h index 82b6e91e05c..2ff6f77111a 100644 --- a/plugins/liberty_parser/include/liberty_parser/liberty_parser.h +++ b/plugins/liberty_parser/include/liberty_parser/liberty_parser.h @@ -75,7 +75,7 @@ namespace hal { u32 line_number; std::vector pin_names; - GateType::PinDirection direction = GateType::PinDirection::none; + PinDirection direction = PinDirection::none; std::string function; std::string x_function; std::string z_function; @@ -88,7 +88,7 @@ namespace hal { u32 line_number; std::string name; - GateType::PinDirection direction = GateType::PinDirection::none; + PinDirection direction = PinDirection::none; std::vector pin_names; std::vector pins; std::map index_to_pin_name; @@ -102,8 +102,8 @@ namespace hal std::string next_state; std::string clear; std::string preset; - GateType::ClearPresetBehavior special_behavior_var1 = GateType::ClearPresetBehavior::invalid; - GateType::ClearPresetBehavior special_behavior_var2 = GateType::ClearPresetBehavior::invalid; + GateType::ClearPresetBehavior special_behavior_var1 = GateType::ClearPresetBehavior::undef; + GateType::ClearPresetBehavior special_behavior_var2 = GateType::ClearPresetBehavior::undef; std::string data_category; std::string data_identifier; }; @@ -116,8 +116,8 @@ namespace hal std::string data_in; std::string clear; std::string preset; - GateType::ClearPresetBehavior special_behavior_var1 = GateType::ClearPresetBehavior::invalid; - GateType::ClearPresetBehavior special_behavior_var2 = GateType::ClearPresetBehavior::invalid; + GateType::ClearPresetBehavior special_behavior_var1 = GateType::ClearPresetBehavior::undef; + GateType::ClearPresetBehavior special_behavior_var2 = GateType::ClearPresetBehavior::undef; }; struct lut_group @@ -156,7 +156,7 @@ namespace hal std::optional parse_cell(TokenStream& library_stream); std::optional parse_type(TokenStream& str); - std::optional parse_pin(TokenStream& str, cell_group& cell, GateType::PinDirection direction = GateType::PinDirection::none, const std::string& external_pin_name = ""); + std::optional parse_pin(TokenStream& str, cell_group& cell, PinDirection direction = PinDirection::none, const std::string& external_pin_name = ""); std::optional parse_pg_pin(TokenStream& str, cell_group& cell); std::optional parse_bus(TokenStream& str, cell_group& cell); std::optional parse_ff(TokenStream& str); diff --git a/plugins/liberty_parser/src/liberty_parser.cpp b/plugins/liberty_parser/src/liberty_parser.cpp index e717ce7769e..3869a2e679a 100644 --- a/plugins/liberty_parser/src/liberty_parser.cpp +++ b/plugins/liberty_parser/src/liberty_parser.cpp @@ -346,7 +346,7 @@ namespace hal return cell; } - std::optional LibertyParser::parse_pin(TokenStream& str, cell_group& cell, GateType::PinDirection direction, const std::string& external_pin_name) + std::optional LibertyParser::parse_pin(TokenStream& str, cell_group& cell, PinDirection direction, const std::string& external_pin_name) { pin_group pin; @@ -437,23 +437,11 @@ namespace hal { pin_str.consume(":", true); auto direction_str = pin_str.consume().string; - if (direction_str == "input") - { - pin.direction = GateType::PinDirection::input; - } - else if (direction_str == "output") + try { - pin.direction = GateType::PinDirection::output; + pin.direction = enum_from_string(direction_str); } - else if (direction_str == "inout") - { - pin.direction = GateType::PinDirection::inout; - } - else if (direction_str == "internal") - { - pin.direction = GateType::PinDirection::internal; - } - else + catch (const std::runtime_error&) { log_warning("liberty_parser", "invalid pin direction '{}' near line {}.", direction_str, pin.line_number); return std::nullopt; @@ -486,7 +474,7 @@ namespace hal } } - if (pin.direction == GateType::PinDirection::none) + if (pin.direction == PinDirection::none) { log_error("liberty_parser", "no pin direction given near line {}.", pin.line_number); return std::nullopt; @@ -529,7 +517,7 @@ namespace hal cell.pin_names.insert(name); pin.pin_names.push_back(name); - pin.direction = GateType::PinDirection::input; + pin.direction = PinDirection::input; while (pin_str.remaining() > 0) { @@ -595,19 +583,19 @@ namespace hal auto direction_str = bus_str.consume().string; if (direction_str == "input") { - bus.direction = GateType::PinDirection::input; + bus.direction = PinDirection::input; } else if (direction_str == "output") { - bus.direction = GateType::PinDirection::output; + bus.direction = PinDirection::output; } else if (direction_str == "inout") { - bus.direction = GateType::PinDirection::inout; + bus.direction = PinDirection::inout; } else if (direction_str == "internal") { - bus.direction = GateType::PinDirection::internal; + bus.direction = PinDirection::internal; } else { @@ -636,7 +624,7 @@ namespace hal bus.index_to_pin_name.emplace(index, pin_name); } - if (bus.direction == GateType::PinDirection::none) + if (bus.direction == PinDirection::none) { log_error("liberty_parser", "no bus direction given near line {}.", bus.line_number); return std::nullopt; @@ -692,7 +680,7 @@ namespace hal Token behav_str = ff_str.consume(); ff_str.consume(";", true); - if(auto behav = enum_from_string(behav_str); behav != GateType::ClearPresetBehavior::invalid) + if (auto behav = enum_from_string(behav_str, GateType::ClearPresetBehavior::undef); behav != GateType::ClearPresetBehavior::undef) { if (next_token == "clear_preset_var1") { @@ -773,7 +761,7 @@ namespace hal Token behav_str = latch_str.consume(); latch_str.consume(";", true); - if(auto behav = enum_from_string(behav_str); behav != GateType::ClearPresetBehavior::invalid) + if (auto behav = enum_from_string(behav_str, GateType::ClearPresetBehavior::undef); behav != GateType::ClearPresetBehavior::undef) { if (next_token == "clear_preset_var1") { @@ -856,12 +844,12 @@ namespace hal std::string func; for (const auto& pin : cell.pins) { - if (pin.direction == GateType::PinDirection::input) + if (pin.direction == PinDirection::input) { has_inputs = true; break; } - else if (pin.direction == GateType::PinDirection::output) + else if (pin.direction == PinDirection::output) { if (has_single_output == true) { @@ -904,12 +892,12 @@ namespace hal // get input and output pins from pin groups for (const auto& pin : cell.pins) { - if (pin.direction == GateType::PinDirection::input || pin.direction == GateType::PinDirection::inout) + if (pin.direction == PinDirection::input || pin.direction == PinDirection::inout) { input_pins.insert(input_pins.end(), pin.pin_names.begin(), pin.pin_names.end()); } - if (pin.direction == GateType::PinDirection::output || pin.direction == GateType::PinDirection::inout) + if (pin.direction == PinDirection::output || pin.direction == PinDirection::inout) { output_pins.insert(output_pins.end(), pin.pin_names.begin(), pin.pin_names.end()); } @@ -960,7 +948,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::state); + gt->assign_pin_type(pin_name, PinType::state); } pin.function = ""; @@ -969,7 +957,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::neg_state); + gt->assign_pin_type(pin_name, PinType::neg_state); } pin.function = ""; @@ -979,7 +967,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::clock); + gt->assign_pin_type(pin_name, PinType::clock); } } } @@ -992,7 +980,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::state); + gt->assign_pin_type(pin_name, PinType::state); } pin.function = ""; @@ -1001,7 +989,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::neg_state); + gt->assign_pin_type(pin_name, PinType::neg_state); } pin.function = ""; @@ -1011,7 +999,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::clock); + gt->assign_pin_type(pin_name, PinType::clock); } } } @@ -1047,7 +1035,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::state); + gt->assign_pin_type(pin_name, PinType::state); } pin.function = ""; @@ -1056,7 +1044,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::neg_state); + gt->assign_pin_type(pin_name, PinType::neg_state); } pin.function = ""; @@ -1066,7 +1054,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::clock); + gt->assign_pin_type(pin_name, PinType::clock); } } } @@ -1079,7 +1067,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::state); + gt->assign_pin_type(pin_name, PinType::state); } pin.function = ""; @@ -1088,7 +1076,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::neg_state); + gt->assign_pin_type(pin_name, PinType::neg_state); } pin.function = ""; @@ -1098,7 +1086,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::clock); + gt->assign_pin_type(pin_name, PinType::clock); } } } @@ -1116,7 +1104,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::lut); + gt->assign_pin_type(pin_name, PinType::lut); } pin.function = ""; @@ -1131,7 +1119,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::lut); + gt->assign_pin_type(pin_name, PinType::lut); } pin.function = ""; @@ -1146,7 +1134,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::power); + gt->assign_pin_type(pin_name, PinType::power); } } @@ -1154,7 +1142,7 @@ namespace hal { for (const auto& pin_name : pin.pin_names) { - gt->assign_pin_type(pin_name, GateType::PinType::ground); + gt->assign_pin_type(pin_name, PinType::ground); } } } @@ -1415,7 +1403,7 @@ namespace hal { UNUSED(bus_name); - if (bus.direction != GateType::PinDirection::output && bus.direction != GateType::PinDirection::inout) + if (bus.direction != PinDirection::output && bus.direction != PinDirection::inout) { continue; } diff --git a/plugins/liberty_parser/test/liberty_parser.cpp b/plugins/liberty_parser/test/liberty_parser.cpp index d0b9d1519b6..5888ee7d719 100644 --- a/plugins/liberty_parser/test/liberty_parser.cpp +++ b/plugins/liberty_parser/test/liberty_parser.cpp @@ -44,8 +44,8 @@ namespace hal { // -- Check the pins EXPECT_EQ(gt->get_input_pins(), std::vector({"VDD", "GND", "I"})); EXPECT_EQ(gt->get_output_pins(), std::vector({"O"})); - EXPECT_EQ(gt->get_pins_of_type(GateType::PinType::power), std::unordered_set({"VDD"})); - EXPECT_EQ(gt->get_pins_of_type(GateType::PinType::ground), std::unordered_set({"GND"})); + EXPECT_EQ(gt->get_pins_of_type(PinType::power), std::unordered_set({"VDD"})); + EXPECT_EQ(gt->get_pins_of_type(PinType::ground), std::unordered_set({"GND"})); // -- Check the boolean functions ASSERT_TRUE(gt->get_boolean_functions().find("O") != gt->get_boolean_functions().end()); EXPECT_EQ(gt->get_boolean_functions().at("O"), @@ -89,7 +89,7 @@ namespace hal { ASSERT_TRUE(gt_asc->get_boolean_functions().find("O3") != gt_asc->get_boolean_functions().end()); EXPECT_EQ(gt_asc->get_boolean_functions().at("O3"), BooleanFunction::from_string("I0 & I1", std::vector({"I0", "I1"}))); - EXPECT_EQ(gt_asc->get_pins_of_type(GateType::PinType::lut), std::unordered_set({"O0", "O2"})); + EXPECT_EQ(gt_asc->get_pins_of_type(PinType::lut), std::unordered_set({"O0", "O2"})); EXPECT_EQ(gt_asc->get_config_data_category(), "test_category"); EXPECT_EQ(gt_asc->get_config_data_identifier(), "test_identifier"); EXPECT_EQ(gt_asc->is_lut_init_ascending(), true); @@ -131,7 +131,7 @@ namespace hal { // Check the content of the created Gate type EXPECT_EQ(gt->get_input_pins(), std::vector({"CLK", "CE", "D", "R", "S"})); EXPECT_EQ(gt->get_output_pins(), std::vector({"Q", "QN", "O"})); - EXPECT_EQ(gt->get_pins_of_type(GateType::PinType::clock), std::unordered_set({"CLK"})); + EXPECT_EQ(gt->get_pins_of_type(PinType::clock), std::unordered_set({"CLK"})); ASSERT_TRUE(gt->get_boolean_functions().find("O") != gt->get_boolean_functions().end()); EXPECT_EQ(gt->get_boolean_functions().at("O"), BooleanFunction::from_string("S & R & D", std::vector({"S", "R", "D"}))); @@ -149,8 +149,8 @@ namespace hal { EXPECT_EQ(gt->get_boolean_functions().at("clear"), BooleanFunction::from_string("R", std::vector({"R"}))); // -- Check the output pins - EXPECT_EQ(gt->get_pins_of_type(GateType::PinType::state), std::unordered_set({"Q"})); - EXPECT_EQ(gt->get_pins_of_type(GateType::PinType::neg_state), std::unordered_set({"QN"})); + EXPECT_EQ(gt->get_pins_of_type(PinType::state), std::unordered_set({"Q"})); + EXPECT_EQ(gt->get_pins_of_type(PinType::neg_state), std::unordered_set({"QN"})); // -- Check the set-reset behaviour EXPECT_EQ(gt->get_clear_preset_behavior(), std::make_pair(GateType::ClearPresetBehavior::L, @@ -203,8 +203,8 @@ namespace hal { EXPECT_EQ(gt->get_boolean_functions().at("clear"), BooleanFunction::from_string("R", std::vector({"R"}))); // -- Check the output pins - EXPECT_EQ(gt->get_pins_of_type(GateType::PinType::state), std::unordered_set({"Q"})); - EXPECT_EQ(gt->get_pins_of_type(GateType::PinType::neg_state), std::unordered_set({"QN"})); + EXPECT_EQ(gt->get_pins_of_type(PinType::state), std::unordered_set({"Q"})); + EXPECT_EQ(gt->get_pins_of_type(PinType::neg_state), std::unordered_set({"QN"})); // -- Check the clear-preset behaviour EXPECT_EQ(gt->get_clear_preset_behavior(), std::make_pair(GateType::ClearPresetBehavior::N, diff --git a/plugins/netlist_simulator/src/netlist_simulator.cpp b/plugins/netlist_simulator/src/netlist_simulator.cpp index 503d97f42bd..ff99f1ae649 100644 --- a/plugins/netlist_simulator/src/netlist_simulator.cpp +++ b/plugins/netlist_simulator/src/netlist_simulator.cpp @@ -101,15 +101,15 @@ namespace hal { if (gate->get_type()->has_property(GateTypeProperty::ff)) { - GateType* gate_type = gate->get_type(); - const std::unordered_map& pin_types = gate_type->get_pin_types(); + GateType* gate_type = gate->get_type(); + const std::unordered_map& pin_types = gate_type->get_pin_types(); SignalValue inv_value = toggle(value); // generate events for (Endpoint* ep : gate->get_fan_out_endpoints()) { - if (pin_types.at(ep->get_pin()) == GateType::PinType::state) + if (pin_types.at(ep->get_pin()) == PinType::state) { Event e; e.affected_net = ep->get_net(); @@ -117,7 +117,7 @@ namespace hal e.time = m_current_time; m_event_queue.push_back(e); } - else if (pin_types.at(ep->get_pin()) == GateType::PinType::neg_state) + else if (pin_types.at(ep->get_pin()) == PinType::neg_state) { Event e; e.affected_net = ep->get_net(); @@ -139,8 +139,8 @@ namespace hal { if (gate->get_type()->has_property(GateTypeProperty::ff)) { - GateType* gate_type = gate->get_type(); - const std::unordered_map& pin_types = gate_type->get_pin_types(); + GateType* gate_type = gate->get_type(); + const std::unordered_map& pin_types = gate_type->get_pin_types(); // extract init string std::string init_str = std::get<1>(gate->get_data(gate_type->get_config_data_category(), gate_type->get_config_data_identifier())); @@ -168,7 +168,7 @@ namespace hal // generate events for (Endpoint* ep : gate->get_fan_out_endpoints()) { - if (pin_types.at(ep->get_pin()) == GateType::PinType::state) + if (pin_types.at(ep->get_pin()) == PinType::state) { Event e; e.affected_net = ep->get_net(); @@ -176,7 +176,7 @@ namespace hal e.time = m_current_time; m_event_queue.push_back(e); } - else if (pin_types.at(ep->get_pin()) == GateType::PinType::neg_state) + else if (pin_types.at(ep->get_pin()) == PinType::neg_state) { Event e; e.affected_net = ep->get_net(); @@ -331,21 +331,21 @@ namespace hal sim_gate->preset_func = gate->get_boolean_function("preset"); sim_gate->clear_func = gate->get_boolean_function("clear"); sim_gate->next_state_func = gate->get_boolean_function("next_state"); - for (auto pin : gate_type->get_pins_of_type(GateType::PinType::state)) + for (auto pin : gate_type->get_pins_of_type(PinType::state)) { if (Net* net = gate->get_fan_out_net(pin); net != nullptr) { sim_gate->state_output_nets.push_back(gate->get_fan_out_net(pin)); } } - for (auto pin : gate_type->get_pins_of_type(GateType::PinType::neg_state)) + for (auto pin : gate_type->get_pins_of_type(PinType::neg_state)) { if (Net* net = gate->get_fan_out_net(pin); net != nullptr) { sim_gate->state_inverted_output_nets.push_back(gate->get_fan_out_net(pin)); } } - for (auto pin : gate_type->get_pins_of_type(GateType::PinType::clock)) + for (auto pin : gate_type->get_pins_of_type(PinType::clock)) { sim_gate->clock_nets.push_back(gate->get_fan_in_net(pin)); } diff --git a/plugins/solve_fsm/src/plugin_solve_fsm.cpp b/plugins/solve_fsm/src/plugin_solve_fsm.cpp index 880f563ee8c..f46947ac53c 100644 --- a/plugins/solve_fsm/src/plugin_solve_fsm.cpp +++ b/plugins/solve_fsm/src/plugin_solve_fsm.cpp @@ -10,7 +10,6 @@ #include "hal_core/netlist/netlist_utils.h" #include "hal_core/netlist/persistent/netlist_serializer.h" #include "hal_core/plugin_system/plugin_manager.h" - #include "z3_utils/include/plugin_z3_utils.h" #include @@ -41,10 +40,11 @@ namespace hal { } - std::map> SolveFsmPlugin::solve_fsm_brute_force(Netlist* nl, const std::vector state_reg, const std::vector transition_logic, const std::string graph_path) { + std::map> SolveFsmPlugin::solve_fsm_brute_force(Netlist* nl, const std::vector state_reg, const std::vector transition_logic, const std::string graph_path) + { // create mapping between (negated) output nets and data input nets of state flip-flops in in order to later replace them. const std::map output_net_to_input_net = find_output_net_to_input_net({state_reg.begin(), state_reg.end()}); - + std::map state_net_to_func; std::map external_ids_to_func; std::vector external_ids; @@ -52,9 +52,11 @@ namespace hal std::vector subgraph_gates = {transition_logic.begin(), transition_logic.end()}; - for (const auto& ff : state_reg) { - const std::unordered_set d_ports = ff->get_type()->get_pins_of_type(GateType::PinType::data); - if (d_ports.size() != 1) { + for (const auto& ff : state_reg) + { + const std::unordered_set d_ports = ff->get_type()->get_pins_of_type(PinType::data); + if (d_ports.size() != 1) + { log_error("Fsm solver", "currently not supporting flip-flops with multiple or no data inputs. ({})", d_ports.size()); } const hal::Net* input_net = ff->get_fan_in_net(*d_ports.begin()); @@ -63,27 +65,33 @@ namespace hal BooleanFunction bf = netlist_utils::get_subgraph_function(input_net, subgraph_gates); // Special case if a flip-flop has another flip-flop as a direct predecessor - if (bf.is_empty()) { - bf = BooleanFunction::from_string(std::to_string(input_net->get_id())); + if (bf.is_empty()) + { + bf = BooleanFunction::from_string(std::to_string(input_net->get_id())); } // find all external inputs. We define external inputs as nets that are inputs to the transition logic but are not bits from the previous state. - for (const auto& id_str : bf.get_variables()) { - u32 id = std::stoi(id_str); + for (const auto& id_str : bf.get_variables()) + { + u32 id = std::stoi(id_str); hal::Net* net = nl->get_net_by_id(id); - if (output_net_to_input_net.find(net) == output_net_to_input_net.end()) { + if (output_net_to_input_net.find(net) == output_net_to_input_net.end()) + { external_ids_to_func.insert({id, BooleanFunction::from_string(id_str)}); - if (std::find(external_ids.begin(), external_ids.end(), id) == external_ids.end()) { + if (std::find(external_ids.begin(), external_ids.end(), id) == external_ids.end()) + { external_ids.push_back(id); } } } // in the transition logic expressions of the next state bits we substitue the output nets of the state flip-flops with their (negated) input net. - for (const auto& [out, in] : output_net_to_input_net) { + for (const auto& [out, in] : output_net_to_input_net) + { // check wether output net is part of the expression std::vector vars = bf.get_variables(); - if (std::find(vars.begin(), vars.end(), std::to_string(out->get_id())) == vars.end()) { + if (std::find(vars.begin(), vars.end(), std::to_string(out->get_id())) == vars.end()) + { continue; } @@ -91,17 +99,19 @@ namespace hal BooleanFunction to = BooleanFunction::from_string(std::to_string(in->get_id())); // check for multidriven nets - if (out->get_sources().size() != 1) { + if (out->get_sources().size() != 1) + { log_error("Fsm solver", "Multidriven nets are not supported! Aborting at Net {}.", out->get_id()); return {}; } // negate if the output stems from the negated state output - const std::string src_pin = out->get_sources().front()->get_pin(); - const std::unordered_set neg_state_pins = out->get_sources().front()->get_gate()->get_type()->get_pins_of_type(GateType::PinType::neg_state); - if (neg_state_pins.find(src_pin) != neg_state_pins.end()) { + const std::string src_pin = out->get_sources().front()->get_pin(); + const std::unordered_set neg_state_pins = out->get_sources().front()->get_gate()->get_type()->get_pins_of_type(PinType::neg_state); + if (neg_state_pins.find(src_pin) != neg_state_pins.end()) + { to = ~to; - } + } bf = bf.substitute(from.to_string(), to); } @@ -110,14 +120,16 @@ namespace hal } const u32 state_size = state_net_to_func.size(); - if (state_size > 64) { + if (state_size > 64) + { log_error("Fsm solver", "Current maximum for state size is 64 bit."); - return{}; + return {}; } - if (external_ids.size() > 64) { + if (external_ids.size() > 64) + { log_error("Fsm solver", "Current maximum for input size is 64 bit."); - return{}; + return {}; } log_info("Fsm solver", "Starting brute force on state with {} bits and {} external inputs.", state_size, external_ids.size()); @@ -127,22 +139,26 @@ namespace hal // TODO this is only necessary because there is no default constructor for z3::expr -> Cannot create fsm transition without ctx. Will need to modify the fsm transition type. z3::context ctx; - for (u64 state = 0; state < (u64(1) << state_size); state++) { + for (u64 state = 0; state < (u64(1) << state_size); state++) + { // generate state map std::unordered_map state_id_str_to_val; - for (u32 state_index = 0; state_index < state_reg.size(); state_index++) { - std::string id_str = std::to_string(state_input_net_ids.at(state_index)); + for (u32 state_index = 0; state_index < state_reg.size(); state_index++) + { + std::string id_str = std::to_string(state_input_net_ids.at(state_index)); BooleanFunction::Value val = ((state >> state_index) & 0x1) ? BooleanFunction::Value::ONE : BooleanFunction::Value::ZERO; state_id_str_to_val.insert({id_str, val}); } // brute force over all external inputs - for (u64 input = 0; input < (u64(1) << external_ids.size()); input++) { + for (u64 input = 0; input < (u64(1) << external_ids.size()); input++) + { // generate input map std::unordered_map input_id_str_to_val; std::map input_id_to_val; - for (u32 input_index = 0; input_index < external_ids.size(); input_index++) { - std::string id_str = std::to_string(external_ids.at(input_index)); + for (u32 input_index = 0; input_index < external_ids.size(); input_index++) + { + std::string id_str = std::to_string(external_ids.at(input_index)); BooleanFunction::Value val = ((input >> input_index) & 0x1) ? BooleanFunction::Value::ONE : BooleanFunction::Value::ZERO; input_id_str_to_val.insert({id_str, val}); input_id_to_val.insert({external_ids.at(input_index), ((input >> input_index) & 0x1)}); @@ -155,16 +171,18 @@ namespace hal // evaluate next state and create transition u64 next_state = 0; - for (u32 next_state_index = 0; next_state_index < state_size; next_state_index++) { + for (u32 next_state_index = 0; next_state_index < state_size; next_state_index++) + { BooleanFunction::Value new_val = state_net_to_func.at(state_input_net_ids.at(next_state_index)).evaluate(id_str_to_val); - if (new_val == BooleanFunction::Value::ONE) { + if (new_val == BooleanFunction::Value::ONE) + { next_state += (1 << next_state_index); } } - + // TODO this conversion is only necessary because there is no default constructor for z3::expr. Will need to modify the fsm transition type. - z3::expr state_expr = ctx.bv_val(state, state_size); - z3::expr next_state_expr = ctx.bv_val(next_state, state_size); + z3::expr state_expr = ctx.bv_val(state, state_size); + z3::expr next_state_expr = ctx.bv_val(next_state, state_size); all_transitions.push_back(FsmTransition(state_expr, next_state_expr, input_id_to_val)); } } @@ -173,7 +191,8 @@ namespace hal all_transitions = merge_transitions(all_transitions); // print state graph to file - if (graph_path != "") { + if (graph_path != "") + { const std::string graph = generate_dot_graph(nl, all_transitions, state_reg); std::ofstream ofs(graph_path); @@ -187,9 +206,11 @@ namespace hal // generate mapping std::map> state_to_successors; - for (const auto& t : all_transitions) { + for (const auto& t : all_transitions) + { // init successors vector - if (state_to_successors.find(t.starting_state) == state_to_successors.end()) { + if (state_to_successors.find(t.starting_state) == state_to_successors.end()) + { state_to_successors.insert({t.starting_state, {}}); } @@ -199,7 +220,13 @@ namespace hal return state_to_successors; } - std::map> SolveFsmPlugin::solve_fsm(Netlist* nl, const std::vector state_reg, const std::vector transition_logic, const std::map initial_state, const std::string graph_path, const u32 timeout) { + std::map> SolveFsmPlugin::solve_fsm(Netlist* nl, + const std::vector state_reg, + const std::vector transition_logic, + const std::map initial_state, + const std::string graph_path, + const u32 timeout) + { // create mapping between (negated) output nets and data input nets of state flip-flops in in order to later replace them. const std::map output_net_to_input_net = find_output_net_to_input_net({state_reg.begin(), state_reg.end()}); @@ -208,7 +235,7 @@ namespace hal // set timeout for z3 solvers z3::params p(ctx); p.set("timeout", (unsigned)timeout); - + // extract z3 functions for each state flip-flop std::map state_net_to_expr; std::map external_ids_to_expr; @@ -216,9 +243,11 @@ namespace hal z3_utils::SubgraphFunctionGenerator g; std::vector subgraph_gates = {transition_logic.begin(), transition_logic.end()}; - for (const auto& ff : state_reg) { - const std::unordered_set d_ports = ff->get_type()->get_pins_of_type(GateType::PinType::data); - if (d_ports.size() != 1) { + for (const auto& ff : state_reg) + { + const std::unordered_set d_ports = ff->get_type()->get_pins_of_type(PinType::data); + if (d_ports.size() != 1) + { log_error("Fsm solver", "currently not supporting flip-flops with multiple or no data inputs. ({})", d_ports.size()); } const hal::Net* input_net = ff->get_fan_in_net(*d_ports.begin()); @@ -229,17 +258,21 @@ namespace hal r.simplify(); // find all external inputs. We define external inputs as nets that are inputs to the transition logic but are not bits from the previous state. - for (const auto& id : ids) { + for (const auto& id : ids) + { hal::Net* net = nl->get_net_by_id(id); - if (output_net_to_input_net.find(net) == output_net_to_input_net.end()) { + if (output_net_to_input_net.find(net) == output_net_to_input_net.end()) + { external_ids_to_expr.insert({id, ctx.bv_const(std::to_string(id).c_str(), 1)}); } } // in the transition logic expressions of the next state bits we substitue the output nets of the state flip-flops with their (negated) input net. - for (const auto& [out, in] : output_net_to_input_net) { + for (const auto& [out, in] : output_net_to_input_net) + { // check wether output net is part of the expression - if (ids.find(out->get_id()) == ids.end()) { + if (ids.find(out->get_id()) == ids.end()) + { continue; } @@ -247,17 +280,19 @@ namespace hal z3::expr to = ctx.bv_const(std::to_string(in->get_id()).c_str(), 1); // check for multidriven nets - if (out->get_sources().size() != 1) { + if (out->get_sources().size() != 1) + { log_error("Fsm solver", "Multidriven nets are not supported! Aborting at Net {}.", out->get_id()); return {}; } // negate if the output stems from the negated state output - const std::string src_pin = out->get_sources().front()->get_pin(); - const std::unordered_set neg_state_pins = out->get_sources().front()->get_gate()->get_type()->get_pins_of_type(GateType::PinType::neg_state); - if (neg_state_pins.find(src_pin) != neg_state_pins.end()) { + const std::string src_pin = out->get_sources().front()->get_pin(); + const std::unordered_set neg_state_pins = out->get_sources().front()->get_gate()->get_type()->get_pins_of_type(PinType::neg_state); + if (neg_state_pins.find(src_pin) != neg_state_pins.end()) + { to = ~to; - } + } z3::expr_vector from_vec(ctx); z3::expr_vector to_vec(ctx); @@ -275,27 +310,35 @@ namespace hal z3::expr next_state_vec(ctx); z3::expr prev_state_vec(ctx); - for (const auto& gate : state_reg) { + for (const auto& gate : state_reg) + { // reconstruct input net id - const std::unordered_set d_ports = gate->get_type()->get_pins_of_type(GateType::PinType::data); - if (d_ports.size() != 1) { + const std::unordered_set d_ports = gate->get_type()->get_pins_of_type(PinType::data); + if (d_ports.size() != 1) + { log_error("Fsm solver", "currently not supporting flip-flops with multiple or no data inputs. ({})", d_ports.size()); } const u32 net_id = gate->get_fan_in_net(*d_ports.begin())->get_id(); // bitvector representing the previous state z3::expr prev_expr = ctx.bv_const((std::to_string(net_id)).c_str(), 1); - if (prev_state_vec.to_string() == "null") { + if (prev_state_vec.to_string() == "null") + { prev_state_vec = prev_expr; - } else { + } + else + { prev_state_vec = z3::concat(prev_state_vec, prev_expr); } // bitvector including all the functions to calculate the next state z3::expr func = state_net_to_expr.at(net_id); - if (next_state_vec.to_string() == "null") { + if (next_state_vec.to_string() == "null") + { next_state_vec = func; - } else { + } + else + { next_state_vec = z3::concat(next_state_vec, func); } } @@ -304,22 +347,32 @@ namespace hal z3::expr inital_state_expr(ctx); // generate initial state - if (initial_state.empty()) { + if (initial_state.empty()) + { inital_state_expr = ctx.bv_val(0x0, state_size); - } else { + } + else + { z3::expr init(ctx); - for (const auto& gate : state_reg) { + for (const auto& gate : state_reg) + { z3::expr temp(ctx); - if (initial_state.find(gate) == initial_state.end()) { + if (initial_state.find(gate) == initial_state.end()) + { log_error("Fsm solver", "Initial state map does not contain value for gate {}. Set to zero.", gate->get_id()); temp = ctx.bv_val(0x0, 1); - } else { + } + else + { temp = ctx.bv_val(initial_state.at(gate), 1); } - if (init.to_string() == "null") { + if (init.to_string() == "null") + { init = temp; - } else { + } + else + { init = z3::concat(init, temp); } } @@ -337,11 +390,13 @@ namespace hal current_successors.push_back(inital_state_expr); q.push_back(inital_state_expr); - while (!q.empty()) { + while (!q.empty()) + { z3::expr n = q.front(); q.pop_front(); - if (visited.find(n.to_string()) != visited.end()) { + if (visited.find(n.to_string()) != visited.end()) + { continue; } visited.insert(n.to_string()); @@ -350,7 +405,8 @@ namespace hal std::vector new_transitions = get_state_successors(prev_state_vec, next_state_vec, n, external_ids_to_expr); all_transitions.insert(all_transitions.end(), new_transitions.begin(), new_transitions.end()); - for (const auto& t : new_transitions) { + for (const auto& t : new_transitions) + { q.push_back(t.end_state_expr); } } @@ -359,7 +415,8 @@ namespace hal all_transitions = merge_transitions(all_transitions); // print state graph to file - if (graph_path != "") { + if (graph_path != "") + { const std::string graph = generate_dot_graph(nl, all_transitions, state_reg); std::ofstream ofs(graph_path); @@ -373,9 +430,11 @@ namespace hal // generate mapping std::map> state_to_successors; - for (const auto& t : all_transitions) { + for (const auto& t : all_transitions) + { // init successors vector - if (state_to_successors.find(t.starting_state) == state_to_successors.end()) { + if (state_to_successors.find(t.starting_state) == state_to_successors.end()) + { state_to_successors.insert({t.starting_state, {}}); } @@ -385,12 +444,16 @@ namespace hal return state_to_successors; } - std::map SolveFsmPlugin::find_output_net_to_input_net(const std::set state_reg) { + std::map SolveFsmPlugin::find_output_net_to_input_net(const std::set state_reg) + { std::map output_net_to_input_net; - for (const auto& ff : state_reg) { - for (const auto& back_net : ff->get_fan_out_nets()) { - const std::unordered_set d_ports = ff->get_type()->get_pins_of_type(GateType::PinType::data); - if (d_ports.size() != 1) { + for (const auto& ff : state_reg) + { + for (const auto& back_net : ff->get_fan_out_nets()) + { + const std::unordered_set d_ports = ff->get_type()->get_pins_of_type(PinType::data); + if (d_ports.size() != 1) + { log_error("Fsm solver", "currently not supporting flip-flops with multiple or no data inputs. ({})", d_ports.size()); } hal::Net* input_net = ff->get_fan_in_net(*d_ports.begin()); @@ -401,36 +464,46 @@ namespace hal return output_net_to_input_net; } - std::vector SolveFsmPlugin::get_state_successors(const z3::expr& prev_state_vec, const z3::expr& next_state_vec, const z3::expr& start_state, const std::map& external_ids_to_expr) { + std::vector + SolveFsmPlugin::get_state_successors(const z3::expr& prev_state_vec, const z3::expr& next_state_vec, const z3::expr& start_state, const std::map& external_ids_to_expr) + { std::vector successor_transitions; - + z3::solver s = z3::solver(prev_state_vec.ctx()); // initialize the previous state vec with the state currently under inspection s.add(prev_state_vec == start_state); // find all possible values for the next state vec - while (true) { + while (true) + { z3::check_result result = s.check(); - - if (result == z3::sat) { + + if (result == z3::sat) + { z3::model m = s.get_model(); z3::expr n = m.eval(next_state_vec); // check wether the next state only depends on the prev state (is numeral) or contains external inputs - if (n.is_numeral()) { + if (n.is_numeral()) + { successor_transitions.push_back({start_state, n, {}}); - } else { + } + else + { // if the next state bit is dependent on external inputs we find those and brute force all combinations of inputs. // this could be ommitted if we just want to know the transitions without the conditions attached to them. std::vector relevant_inputs = get_relevant_external_inputs(n, external_ids_to_expr); - for (u64 i = 0; i < pow(2, relevant_inputs.size()); i++) { + for (u64 i = 0; i < pow(2, relevant_inputs.size()); i++) + { hal::FsmTransition transition = generate_transition_with_inputs(start_state, n, relevant_inputs, i); successor_transitions.push_back(transition); } } s.add(next_state_vec != n); - } else { + } + else + { break; } } @@ -438,12 +511,15 @@ namespace hal return successor_transitions; } - std::vector SolveFsmPlugin::get_relevant_external_inputs(const z3::expr& state, const std::map& external_ids_to_expr) { + std::vector SolveFsmPlugin::get_relevant_external_inputs(const z3::expr& state, const std::map& external_ids_to_expr) + { std::vector relevant_inputs; - + const std::string str = state.to_string(); - for (const auto& [id, _] : external_ids_to_expr) { - if (str.find("|" + std::to_string(id) + "|") != std::string::npos) { + for (const auto& [id, _] : external_ids_to_expr) + { + if (str.find("|" + std::to_string(id) + "|") != std::string::npos) + { relevant_inputs.push_back(id); } } @@ -451,15 +527,17 @@ namespace hal return relevant_inputs; } - FsmTransition SolveFsmPlugin::generate_transition_with_inputs(const z3::expr& start_state, const z3::expr& state, const std::vector& inputs, const u64 input_values) { + FsmTransition SolveFsmPlugin::generate_transition_with_inputs(const z3::expr& start_state, const z3::expr& state, const std::vector& inputs, const u64 input_values) + { z3::solver s = z3::solver(state.ctx()); // generate a mapping from external input net to value and initialize it in the solver. std::map input_id_to_val; - for (u32 i = 0; i < inputs.size(); i++) { - u64 val = (input_values >> i) & 0x1; + for (u32 i = 0; i < inputs.size(); i++) + { + u64 val = (input_values >> i) & 0x1; z3::expr val_expr = state.ctx().bv_val(val, 1); - z3::expr id_expr = state.ctx().bv_const(std::to_string(inputs.at(i)).c_str(), 1); + z3::expr id_expr = state.ctx().bv_const(std::to_string(inputs.at(i)).c_str(), 1); s.add(id_expr == val_expr); input_id_to_val.insert({inputs.at(i), val}); @@ -467,30 +545,36 @@ namespace hal // evaluate the state reachable under the set input values. s.check(); - z3::model m = s.get_model(); + z3::model m = s.get_model(); z3::expr eval_state = m.eval(state); return {start_state, eval_state, input_id_to_val}; } - std::vector SolveFsmPlugin::merge_transitions(const std::vector& transitions) { + std::vector SolveFsmPlugin::merge_transitions(const std::vector& transitions) + { std::vector m_transitions; std::set already_merged; - for (u32 i = 0; i < transitions.size(); i++) { - if (already_merged.find(i) != already_merged.end()) { + for (u32 i = 0; i < transitions.size(); i++) + { + if (already_merged.find(i) != already_merged.end()) + { continue; } hal::FsmTransition n_transition = transitions.at(i); - - for (u32 j = 0; j < transitions.size(); j++) { - if (i == j) { + + for (u32 j = 0; j < transitions.size(); j++) + { + if (i == j) + { continue; } - if (transitions.at(i).starting_state == transitions.at(j).starting_state && transitions.at(i).end_state == transitions.at(j).end_state) { + if (transitions.at(i).starting_state == transitions.at(j).starting_state && transitions.at(i).end_state == transitions.at(j).end_state) + { n_transition = n_transition.merge(transitions.at(j)); already_merged.insert(j); } @@ -503,30 +587,39 @@ namespace hal return m_transitions; } - std::string SolveFsmPlugin::generate_state_transition_table(const Netlist* nl, const std::vector& transitions, const std::map& external_ids_to_expr) { + std::string SolveFsmPlugin::generate_state_transition_table(const Netlist* nl, const std::vector& transitions, const std::map& external_ids_to_expr) + { std::string header_str = " CURRENT STATE | "; - for (const auto& [ex_id, _] : external_ids_to_expr) { + for (const auto& [ex_id, _] : external_ids_to_expr) + { header_str += nl->get_net_by_id(ex_id)->get_name() + " | "; } header_str += "NEXT STATE"; std::string body_str; - for (const auto& t : transitions) { - if (t.input_ids_to_values.empty()) { + for (const auto& t : transitions) + { + if (t.input_ids_to_values.empty()) + { body_str += std::to_string(t.starting_state) + " | "; - for (u32 i = 0; i < external_ids_to_expr.size(); i++) { - body_str += "X | "; + for (u32 i = 0; i < external_ids_to_expr.size(); i++) + { + body_str += "X | "; } body_str += std::to_string(t.end_state) + "\n"; } - - for (const auto& mapping : t.input_ids_to_values) { + for (const auto& mapping : t.input_ids_to_values) + { body_str += std::to_string(t.starting_state) + " | "; - for (const auto& [ex_id, _] : external_ids_to_expr) { - if (mapping.find(ex_id) != mapping.end()) { + for (const auto& [ex_id, _] : external_ids_to_expr) + { + if (mapping.find(ex_id) != mapping.end()) + { body_str += std::to_string(mapping.at(ex_id)) + " | "; - } else { + } + else + { body_str += "X | "; } } @@ -537,26 +630,30 @@ namespace hal return header_str + "\n" + body_str; } - std::string generate_legend(const std::vector& state_reg) { + std::string generate_legend(const std::vector& state_reg) + { // shape = box std::string name_str = ""; - for (const auto& reg : state_reg) { + for (const auto& reg : state_reg) + { name_str = name_str + reg->get_name(); name_str += ", "; } - name_str = name_str.substr(0, name_str.size()-2); + name_str = name_str.substr(0, name_str.size() - 2); - return "legend[label=\"" + name_str + + "\", shape= box]" + "\n"; + return "legend[label=\"" + name_str + +"\", shape= box]" + "\n"; } - - std::string SolveFsmPlugin::generate_dot_graph(const Netlist* nl, const std::vector& transitions, const std::vector& state_reg) { + + std::string SolveFsmPlugin::generate_dot_graph(const Netlist* nl, const std::vector& transitions, const std::vector& state_reg) + { std::string graph_str = "digraph {\n"; graph_str += generate_legend(state_reg); - for (const auto& t : transitions) { + for (const auto& t : transitions) + { graph_str += t.to_dot_string(nl, state_reg.size()); } diff --git a/plugins/vhdl_verilog_parsers/include/vhdl_verilog_parsers/hdl_parser_template.h b/plugins/vhdl_verilog_parsers/include/vhdl_verilog_parsers/hdl_parser_template.h index 5a1976186a5..5ba7d6aac29 100644 --- a/plugins/vhdl_verilog_parsers/include/vhdl_verilog_parsers/hdl_parser_template.h +++ b/plugins/vhdl_verilog_parsers/include/vhdl_verilog_parsers/hdl_parser_template.h @@ -1547,7 +1547,7 @@ namespace hal } // cache pin types - std::unordered_map pin_to_direction; + std::unordered_map pin_to_direction; if constexpr (std::is_same::value) { pin_to_direction = new_gate->get_type()->get_pin_directions(); @@ -1581,12 +1581,12 @@ namespace hal if (const auto it = pin_to_direction.find(port); it != pin_to_direction.end()) { - if (it->second == GateType::PinDirection::input || it->second == GateType::PinDirection::inout) + if (it->second == PinDirection::input || it->second == PinDirection::inout) { is_input = true; } - if (it->second == GateType::PinDirection::output || it->second == GateType::PinDirection::inout) + if (it->second == PinDirection::output || it->second == PinDirection::inout) { is_output = true; } diff --git a/src/netlist/gate.cpp b/src/netlist/gate.cpp index 789cefed42f..69ea46ab356 100644 --- a/src/netlist/gate.cpp +++ b/src/netlist/gate.cpp @@ -152,7 +152,7 @@ namespace hal if (m_type->has_property(GateTypeProperty::lut)) { - auto lut_pins = m_type->get_pins_of_type(GateType::PinType::lut); + auto lut_pins = m_type->get_pins_of_type(PinType::lut); if (std::find(lut_pins.begin(), lut_pins.end(), name) != lut_pins.end()) { return get_lut_function(name); @@ -189,7 +189,7 @@ namespace hal if (!only_custom_functions && m_type->has_property(GateTypeProperty::lut)) { - for (auto pin : m_type->get_pins_of_type(GateType::PinType::lut)) + for (auto pin : m_type->get_pins_of_type(PinType::lut)) { res.emplace(pin, get_lut_function(pin)); } diff --git a/src/netlist/gate_library/gate_type.cpp b/src/netlist/gate_library/gate_type.cpp index cd8e9774f04..a64d6313463 100644 --- a/src/netlist/gate_library/gate_type.cpp +++ b/src/netlist/gate_library/gate_type.cpp @@ -5,32 +5,18 @@ namespace hal { template<> - std::vector EnumStrings::data = {"combinational", "sequential", "power", "ground", "lut", "ff", "latch", "ram", "io", "dsp", "mux", "buffer", "carry", "invalid"}; + std::vector EnumStrings::data = {"combinational", "sequential", "power", "ground", "lut", "ff", "latch", "ram", "io", "dsp", "mux", "buffer", "carry"}; template<> - std::vector EnumStrings::data = {"L", "H", "N", "T", "X", "invalid"}; - - const std::unordered_map GateType::m_pin_direction_to_string = {{PinDirection::none, "none"}, - {PinDirection::input, "input"}, - {PinDirection::output, "output"}, - {PinDirection::inout, "inout"}, - {PinDirection::internal, "internal"}}; - const std::unordered_map GateType::m_pin_type_to_string = {{PinType::none, "none"}, - {PinType::power, "power"}, - {PinType::ground, "ground"}, - {PinType::lut, "lut"}, - {PinType::state, "state"}, - {PinType::neg_state, "neg_state"}, - {PinType::clock, "clock"}, - {PinType::enable, "enable"}, - {PinType::set, "set"}, - {PinType::reset, "reset"}, - {PinType::data, "data"}, - {PinType::address, "address"}, - {PinType::io_pad, "io_pad"}, - {PinType::select, "select"}}; - - const std::unordered_map> GateType::m_direction_to_types = { + std::vector EnumStrings::data = {"L", "H", "N", "T", "X", "undef"}; + + template<> + std::vector EnumStrings::data = {"none", "input", "output", "inout", "internal"}; + + template<> + std::vector EnumStrings::data = {"none", "power", "ground", "lut", "state", "neg_state", "clock", "enable", "set", "reset", "data", "address", "io_pad", "select"}; + + const std::unordered_map> GateType::m_direction_to_types = { {PinDirection::none, {}}, {PinDirection::input, {PinType::none, PinType::power, PinType::ground, PinType::clock, PinType::enable, PinType::set, PinType::reset, PinType::data, PinType::address, PinType::io_pad, PinType::select}}, @@ -81,16 +67,6 @@ namespace hal return os << gt.to_string(); } - std::ostream& operator<<(std::ostream& os, GateType::PinDirection direction) - { - return os << GateType::m_pin_direction_to_string.at(direction); - } - - std::ostream& operator<<(std::ostream& os, GateType::PinType pin_type) - { - return os << GateType::m_pin_type_to_string.at(pin_type); - } - bool GateType::operator==(const GateType& other) const { return ((m_id == other.get_id()) && (m_gate_library == other.get_gate_library())); @@ -190,7 +166,7 @@ namespace hal return m_pins; } - GateType::PinDirection GateType::get_pin_direction(const std::string& pin) const + PinDirection GateType::get_pin_direction(const std::string& pin) const { if (const auto it = m_pin_to_direction.find(pin); it != m_pin_to_direction.end()) { @@ -200,7 +176,7 @@ namespace hal return PinDirection::internal; } - const std::unordered_map& GateType::get_pin_directions() const + const std::unordered_map& GateType::get_pin_directions() const { return m_pin_to_direction; } @@ -232,11 +208,11 @@ namespace hal } } - log_error("gate_library", "could not assign type '{}' to pin '{}' of gate type '{}'.", m_pin_type_to_string.at(pin_type), pin, m_name); + log_error("gate_library", "could not assign type '{}' to pin '{}' of gate type '{}'.", enum_to_string(pin_type), pin, m_name); return false; } - GateType::PinType GateType::get_pin_type(const std::string& pin) const + PinType GateType::get_pin_type(const std::string& pin) const { if (const auto it = m_pin_to_type.find(pin); it != m_pin_to_type.end()) { @@ -246,7 +222,7 @@ namespace hal return PinType::none; } - const std::unordered_map& GateType::get_pin_types() const + const std::unordered_map& GateType::get_pin_types() const { return m_pin_to_type; } diff --git a/src/netlist/netlist_utils.cpp b/src/netlist/netlist_utils.cpp index 324e9528066..6717a55994d 100644 --- a/src/netlist/netlist_utils.cpp +++ b/src/netlist/netlist_utils.cpp @@ -559,7 +559,7 @@ namespace hal func = func.optimize_constants(); std::string func_str = func.to_string(); - std::unordered_set in_pins = gt->get_pins_of_direction(GateType::PinDirection::input); + std::unordered_set in_pins = gt->get_pins_of_direction(PinDirection::input); if (in_pins.find(func_str) != in_pins.end()) { Net* out_net = out_endpoint->get_net(); diff --git a/src/python_bindings/bindings/gate_type.cpp b/src/python_bindings/bindings/gate_type.cpp index 240dba56b47..6e3cc967ff9 100644 --- a/src/python_bindings/bindings/gate_type.cpp +++ b/src/python_bindings/bindings/gate_type.cpp @@ -20,40 +20,39 @@ namespace hal .value("mux", GateTypeProperty::mux, R"(MUX gate type.)") .value("buffer", GateTypeProperty::buffer, R"(Buffer gate type.)") .value("carry", GateTypeProperty::carry, R"(Carry gate type.)") - .value("invalid", GateTypeProperty::invalid, R"(Invalid property.)") .export_values(); - py::class_> py_gate_type(m, "GateType", R"( - A gate type contains information about its internals such as input and output pins as well as its Boolean functions. - )"); - - py::enum_(py_gate_type, "PinDirection", R"( + py::enum_(m, "PinDirection", R"( Defines the direction of a pin. )") - .value("none", GateType::PinDirection::none, R"(Invalid pin.)") - .value("input", GateType::PinDirection::input, R"(Input pin.)") - .value("output", GateType::PinDirection::output, R"(Output pin.)") - .value("inout", GateType::PinDirection::inout, R"(Inout pin.)") - .value("internal", GateType::PinDirection::internal, R"(Internal pin.)") + .value("none", PinDirection::none, R"(Invalid pin.)") + .value("input", PinDirection::input, R"(Input pin.)") + .value("output", PinDirection::output, R"(Output pin.)") + .value("inout", PinDirection::inout, R"(Inout pin.)") + .value("internal", PinDirection::internal, R"(Internal pin.)") .export_values(); - py::enum_(py_gate_type, "PinType", R"(Defines the type of a pin.)") - .value("none", GateType::PinType::none, R"(Default pin.)") - .value("power", GateType::PinType::power, R"(Power pin.)") - .value("ground", GateType::PinType::ground, R"(Ground pin.)") - .value("lut", GateType::PinType::lut, R"(Pin that generates output from LUT initialization string.)") - .value("state", GateType::PinType::state, R"(Pin that generates output from internal state.)") - .value("neg_state", GateType::PinType::neg_state, R"(Pin that generates output from negated internal state.)") - .value("clock", GateType::PinType::clock, R"(Clock pin.)") - .value("enable", GateType::PinType::enable, R"(Enable pin.)") - .value("set", GateType::PinType::set, R"(Set pin.)") - .value("reset", GateType::PinType::reset, R"(Reset pin.)") - .value("data", GateType::PinType::data, R"(Data pin.)") - .value("address", GateType::PinType::address, R"(Address pin.)") - .value("io_pad", GateType::PinType::io_pad, R"(IO pad pin.)") - .value("select", GateType::PinType::select, R"(Select pin.)") + py::enum_(m, "PinType", R"(Defines the type of a pin.)") + .value("none", PinType::none, R"(Default pin.)") + .value("power", PinType::power, R"(Power pin.)") + .value("ground", PinType::ground, R"(Ground pin.)") + .value("lut", PinType::lut, R"(Pin that generates output from LUT initialization string.)") + .value("state", PinType::state, R"(Pin that generates output from internal state.)") + .value("neg_state", PinType::neg_state, R"(Pin that generates output from negated internal state.)") + .value("clock", PinType::clock, R"(Clock pin.)") + .value("enable", PinType::enable, R"(Enable pin.)") + .value("set", PinType::set, R"(Set pin.)") + .value("reset", PinType::reset, R"(Reset pin.)") + .value("data", PinType::data, R"(Data pin.)") + .value("address", PinType::address, R"(Address pin.)") + .value("io_pad", PinType::io_pad, R"(IO pad pin.)") + .value("select", PinType::select, R"(Select pin.)") .export_values(); + py::class_> py_gate_type(m, "GateType", R"( + A gate type contains information about its internals such as input and output pins as well as its Boolean functions. + )"); + py::enum_(py_gate_type, "ClearPresetBehavior", R"( Defines the behavior of the gate type in case both clear and preset are active at the same time. )") @@ -62,7 +61,7 @@ namespace hal .value("N", GateType::ClearPresetBehavior::N, R"(Do not change the internal state.)") .value("T", GateType::ClearPresetBehavior::T, R"(Toggle, i.e., invert the internal state.)") .value("X", GateType::ClearPresetBehavior::X, R"(Set the internal state to 'X'.)") - .value("invalid", GateType::ClearPresetBehavior::invalid, R"(Invalid bahavior, used by default.)") + .value("undef", GateType::ClearPresetBehavior::undef, R"(Invalid bahavior, used by default.)") .export_values(); py_gate_type.def_property_readonly("id", &GateType::get_id, R"( diff --git a/tests/netlist/gate.cpp b/tests/netlist/gate.cpp index a27949d8ead..4d9195b7684 100644 --- a/tests/netlist/gate.cpp +++ b/tests/netlist/gate.cpp @@ -866,8 +866,8 @@ namespace hal lut->add_input_pins(input_pins); lut->add_output_pins(output_pins); - lut->assign_pin_type("O_LUT", GateType::PinType::lut); - lut->assign_pin_type("O_LUT_other", GateType::PinType::lut); + lut->assign_pin_type("O_LUT", PinType::lut); + lut->assign_pin_type("O_LUT_other", PinType::lut); lut->set_lut_init_ascending(true); lut->set_config_data_identifier("data_identifier"); lut->set_config_data_category("data_category"); diff --git a/tests/netlist/gate_type.cpp b/tests/netlist/gate_type.cpp index a9727cdcc50..0d00f2a4255 100644 --- a/tests/netlist/gate_type.cpp +++ b/tests/netlist/gate_type.cpp @@ -161,54 +161,54 @@ namespace hal ss.str(std::string()); // pin direction to ostream - ss << GateType::PinDirection::input; + ss << PinDirection::input; EXPECT_EQ(ss.str(), "input"); ss.str(std::string()); - ss << GateType::PinDirection::output; + ss << PinDirection::output; EXPECT_EQ(ss.str(), "output"); ss.str(std::string()); - ss << GateType::PinDirection::inout; + ss << PinDirection::inout; EXPECT_EQ(ss.str(), "inout"); ss.str(std::string()); - ss << GateType::PinDirection::internal; + ss << PinDirection::internal; EXPECT_EQ(ss.str(), "internal"); ss.str(std::string()); // pin type to ostream - ss << GateType::PinType::none; + ss << PinType::none; EXPECT_EQ(ss.str(), "none"); ss.str(std::string()); - ss << GateType::PinType::power; + ss << PinType::power; EXPECT_EQ(ss.str(), "power"); ss.str(std::string()); - ss << GateType::PinType::ground; + ss << PinType::ground; EXPECT_EQ(ss.str(), "ground"); ss.str(std::string()); - ss << GateType::PinType::lut; + ss << PinType::lut; EXPECT_EQ(ss.str(), "lut"); ss.str(std::string()); - ss << GateType::PinType::state; + ss << PinType::state; EXPECT_EQ(ss.str(), "state"); ss.str(std::string()); - ss << GateType::PinType::neg_state; + ss << PinType::neg_state; EXPECT_EQ(ss.str(), "neg_state"); ss.str(std::string()); - ss << GateType::PinType::clock; + ss << PinType::clock; EXPECT_EQ(ss.str(), "clock"); ss.str(std::string()); - ss << GateType::PinType::enable; + ss << PinType::enable; EXPECT_EQ(ss.str(), "enable"); ss.str(std::string()); - ss << GateType::PinType::set; + ss << PinType::set; EXPECT_EQ(ss.str(), "set"); ss.str(std::string()); - ss << GateType::PinType::reset; + ss << PinType::reset; EXPECT_EQ(ss.str(), "reset"); ss.str(std::string()); - ss << GateType::PinType::data; + ss << PinType::data; EXPECT_EQ(ss.str(), "data"); ss.str(std::string()); - ss << GateType::PinType::address; + ss << PinType::address; EXPECT_EQ(ss.str(), "address"); ss.str(std::string()); @@ -237,23 +237,23 @@ namespace hal { GateType* gt = gl.create_gate_type("dummy1", {GateTypeProperty::combinational}); ASSERT_NE(gt, nullptr); - EXPECT_TRUE(gt->add_pin("I0", GateType::PinDirection::input)); - EXPECT_TRUE(gt->add_pins({"I1", "I2"}, GateType::PinDirection::input)); + EXPECT_TRUE(gt->add_pin("I0", PinDirection::input)); + EXPECT_TRUE(gt->add_pins({"I1", "I2"}, PinDirection::input)); EXPECT_EQ(gt->get_pins(), std::vector({"I0", "I1", "I2"})); EXPECT_EQ(gt->get_input_pins(), std::vector({"I0", "I1", "I2"})); EXPECT_TRUE(gt->get_output_pins().empty()); - EXPECT_EQ(gt->get_pins_of_direction(GateType::PinDirection::input), std::unordered_set({"I0", "I1", "I2"})); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::output).empty()); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::inout).empty()); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::internal).empty()); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::none).empty()); - EXPECT_EQ(gt->get_pin_direction("I0"), GateType::PinDirection::input); - EXPECT_EQ(gt->get_pin_direction("I1"), GateType::PinDirection::input); - EXPECT_EQ(gt->get_pin_direction("I2"), GateType::PinDirection::input); - std::unordered_map direction_map = { - {"I0", GateType::PinDirection::input}, - {"I1", GateType::PinDirection::input}, - {"I2", GateType::PinDirection::input}}; + EXPECT_EQ(gt->get_pins_of_direction(PinDirection::input), std::unordered_set({"I0", "I1", "I2"})); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::output).empty()); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::inout).empty()); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::internal).empty()); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::none).empty()); + EXPECT_EQ(gt->get_pin_direction("I0"), PinDirection::input); + EXPECT_EQ(gt->get_pin_direction("I1"), PinDirection::input); + EXPECT_EQ(gt->get_pin_direction("I2"), PinDirection::input); + std::unordered_map direction_map = { + {"I0", PinDirection::input}, + {"I1", PinDirection::input}, + {"I2", PinDirection::input}}; EXPECT_EQ(gt->get_pin_directions(), direction_map); } @@ -261,23 +261,23 @@ namespace hal { GateType* gt = gl.create_gate_type("dummy2", {GateTypeProperty::combinational}); ASSERT_NE(gt, nullptr); - EXPECT_TRUE(gt->add_pin("O0", GateType::PinDirection::output)); - EXPECT_TRUE(gt->add_pins({"O1", "O2"}, GateType::PinDirection::output)); + EXPECT_TRUE(gt->add_pin("O0", PinDirection::output)); + EXPECT_TRUE(gt->add_pins({"O1", "O2"}, PinDirection::output)); EXPECT_EQ(gt->get_pins(), std::vector({"O0", "O1", "O2"})); EXPECT_TRUE(gt->get_input_pins().empty()); EXPECT_EQ(gt->get_output_pins(), std::vector({"O0", "O1", "O2"})); - EXPECT_EQ(gt->get_pins_of_direction(GateType::PinDirection::output), std::unordered_set({"O0", "O1", "O2"})); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::input).empty()); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::inout).empty()); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::internal).empty()); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::none).empty()); - EXPECT_EQ(gt->get_pin_direction("O0"), GateType::PinDirection::output); - EXPECT_EQ(gt->get_pin_direction("O1"), GateType::PinDirection::output); - EXPECT_EQ(gt->get_pin_direction("O2"), GateType::PinDirection::output); - std::unordered_map direction_map = { - {"O0", GateType::PinDirection::output}, - {"O1", GateType::PinDirection::output}, - {"O2", GateType::PinDirection::output}}; + EXPECT_EQ(gt->get_pins_of_direction(PinDirection::output), std::unordered_set({"O0", "O1", "O2"})); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::input).empty()); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::inout).empty()); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::internal).empty()); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::none).empty()); + EXPECT_EQ(gt->get_pin_direction("O0"), PinDirection::output); + EXPECT_EQ(gt->get_pin_direction("O1"), PinDirection::output); + EXPECT_EQ(gt->get_pin_direction("O2"), PinDirection::output); + std::unordered_map direction_map = { + {"O0", PinDirection::output}, + {"O1", PinDirection::output}, + {"O2", PinDirection::output}}; EXPECT_EQ(gt->get_pin_directions(), direction_map); } @@ -285,23 +285,23 @@ namespace hal { GateType* gt = gl.create_gate_type("dummy3", {GateTypeProperty::combinational}); ASSERT_NE(gt, nullptr); - EXPECT_TRUE(gt->add_pin("IO0", GateType::PinDirection::inout)); - EXPECT_TRUE(gt->add_pins({"IO1", "IO2"}, GateType::PinDirection::inout)); + EXPECT_TRUE(gt->add_pin("IO0", PinDirection::inout)); + EXPECT_TRUE(gt->add_pins({"IO1", "IO2"}, PinDirection::inout)); EXPECT_EQ(gt->get_pins(), std::vector({"IO0", "IO1", "IO2"})); EXPECT_EQ(gt->get_input_pins(), std::vector({"IO0", "IO1", "IO2"})); EXPECT_EQ(gt->get_output_pins(), std::vector({"IO0", "IO1", "IO2"})); - EXPECT_EQ(gt->get_pins_of_direction(GateType::PinDirection::inout), std::unordered_set({"IO0", "IO1", "IO2"})); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::input).empty()); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::output).empty()); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::internal).empty()); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::none).empty()); - EXPECT_EQ(gt->get_pin_direction("IO0"), GateType::PinDirection::inout); - EXPECT_EQ(gt->get_pin_direction("IO1"), GateType::PinDirection::inout); - EXPECT_EQ(gt->get_pin_direction("IO2"), GateType::PinDirection::inout); - std::unordered_map direction_map = { - {"IO0", GateType::PinDirection::inout}, - {"IO1", GateType::PinDirection::inout}, - {"IO2", GateType::PinDirection::inout}}; + EXPECT_EQ(gt->get_pins_of_direction(PinDirection::inout), std::unordered_set({"IO0", "IO1", "IO2"})); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::input).empty()); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::output).empty()); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::internal).empty()); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::none).empty()); + EXPECT_EQ(gt->get_pin_direction("IO0"), PinDirection::inout); + EXPECT_EQ(gt->get_pin_direction("IO1"), PinDirection::inout); + EXPECT_EQ(gt->get_pin_direction("IO2"), PinDirection::inout); + std::unordered_map direction_map = { + {"IO0", PinDirection::inout}, + {"IO1", PinDirection::inout}, + {"IO2", PinDirection::inout}}; EXPECT_EQ(gt->get_pin_directions(), direction_map); } @@ -309,23 +309,23 @@ namespace hal { GateType* gt = gl.create_gate_type("dummy4", {GateTypeProperty::combinational}); ASSERT_NE(gt, nullptr); - EXPECT_TRUE(gt->add_pin("INT0", GateType::PinDirection::internal)); - EXPECT_TRUE(gt->add_pins({"INT1", "INT2"}, GateType::PinDirection::internal)); + EXPECT_TRUE(gt->add_pin("INT0", PinDirection::internal)); + EXPECT_TRUE(gt->add_pins({"INT1", "INT2"}, PinDirection::internal)); EXPECT_EQ(gt->get_pins(), std::vector({"INT0", "INT1", "INT2"})); EXPECT_TRUE(gt->get_input_pins().empty()); EXPECT_TRUE(gt->get_output_pins().empty()); - EXPECT_EQ(gt->get_pins_of_direction(GateType::PinDirection::internal), std::unordered_set({"INT0", "INT1", "INT2"})); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::input).empty()); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::output).empty()); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::inout).empty()); - EXPECT_TRUE(gt->get_pins_of_direction(GateType::PinDirection::none).empty()); - EXPECT_EQ(gt->get_pin_direction("INT0"), GateType::PinDirection::internal); - EXPECT_EQ(gt->get_pin_direction("INT1"), GateType::PinDirection::internal); - EXPECT_EQ(gt->get_pin_direction("INT2"), GateType::PinDirection::internal); - std::unordered_map direction_map = { - {"INT0", GateType::PinDirection::internal}, - {"INT1", GateType::PinDirection::internal}, - {"INT2", GateType::PinDirection::internal}}; + EXPECT_EQ(gt->get_pins_of_direction(PinDirection::internal), std::unordered_set({"INT0", "INT1", "INT2"})); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::input).empty()); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::output).empty()); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::inout).empty()); + EXPECT_TRUE(gt->get_pins_of_direction(PinDirection::none).empty()); + EXPECT_EQ(gt->get_pin_direction("INT0"), PinDirection::internal); + EXPECT_EQ(gt->get_pin_direction("INT1"), PinDirection::internal); + EXPECT_EQ(gt->get_pin_direction("INT2"), PinDirection::internal); + std::unordered_map direction_map = { + {"INT0", PinDirection::internal}, + {"INT1", PinDirection::internal}, + {"INT2", PinDirection::internal}}; EXPECT_EQ(gt->get_pin_directions(), direction_map); } @@ -333,13 +333,13 @@ namespace hal { GateType* gt = gl.create_gate_type("dummy5", {GateTypeProperty::combinational}); ASSERT_NE(gt, nullptr); - EXPECT_TRUE(gt->add_pin("A", GateType::PinDirection::input)); + EXPECT_TRUE(gt->add_pin("A", PinDirection::input)); EXPECT_EQ(gt->get_pins(), std::vector({"A"})); - EXPECT_FALSE(gt->add_pin("A", GateType::PinDirection::input)); + EXPECT_FALSE(gt->add_pin("A", PinDirection::input)); EXPECT_EQ(gt->get_pins(), std::vector({"A"})); - EXPECT_FALSE(gt->add_pin("A", GateType::PinDirection::output)); + EXPECT_FALSE(gt->add_pin("A", PinDirection::output)); EXPECT_EQ(gt->get_pins(), std::vector({"A"})); - EXPECT_EQ(gt->get_pin_direction("A"), GateType::PinDirection::input); + EXPECT_EQ(gt->get_pin_direction("A"), PinDirection::input); } TEST_END @@ -368,7 +368,7 @@ namespace hal { GateType* gt = gl.create_gate_type("dummy1", {GateTypeProperty::combinational}); ASSERT_NE(gt, nullptr); - EXPECT_TRUE(gt->add_pins({"A(0)", "A(1)", "B(0)", "B(1)", "C(0)", "C(1)"}, GateType::PinDirection::input)); + EXPECT_TRUE(gt->add_pins({"A(0)", "A(1)", "B(0)", "B(1)", "C(0)", "C(1)"}, PinDirection::input)); EXPECT_TRUE(gt->assign_pin_group("A", index_to_pin_a)); EXPECT_TRUE(gt->assign_pin_group("B", index_to_pin_b)); @@ -381,7 +381,7 @@ namespace hal GateType* gt = gl.create_gate_type("dummy2", {GateTypeProperty::combinational}); ASSERT_NE(gt, nullptr); - EXPECT_TRUE(gt->add_pins({"A(0)", "A(1)"}, GateType::PinDirection::input)); + EXPECT_TRUE(gt->add_pins({"A(0)", "A(1)"}, PinDirection::input)); EXPECT_TRUE(gt->assign_pin_group("A", index_to_pin_a)); EXPECT_EQ(gt->get_pin_groups(), groups_a); EXPECT_FALSE(gt->assign_pin_group("A", index_to_pin_a)); @@ -418,46 +418,46 @@ namespace hal std::unordered_set in_pins = {"I0", "I1"}; std::unordered_set out_pins = {"O"}; - std::unordered_map pin_to_type; + std::unordered_map pin_to_type; - EXPECT_TRUE(gt->add_pins({"I0", "I1"}, GateType::PinDirection::input, GateType::PinType::ground)); - EXPECT_TRUE(gt->add_pins({"O"}, GateType::PinDirection::output)); + EXPECT_TRUE(gt->add_pins({"I0", "I1"}, PinDirection::input, PinType::ground)); + EXPECT_TRUE(gt->add_pins({"O"}, PinDirection::output)); - EXPECT_EQ(gt->get_pin_type("I0"), GateType::PinType::ground); - EXPECT_EQ(gt->get_pin_type("I1"), GateType::PinType::ground); - EXPECT_EQ(gt->get_pin_type("O"), GateType::PinType::none); + EXPECT_EQ(gt->get_pin_type("I0"), PinType::ground); + EXPECT_EQ(gt->get_pin_type("I1"), PinType::ground); + EXPECT_EQ(gt->get_pin_type("O"), PinType::none); - ASSERT_TRUE(gt->assign_pin_type("I0", GateType::PinType::power)); - ASSERT_TRUE(gt->assign_pin_type("I1", GateType::PinType::power)); - ASSERT_FALSE(gt->assign_pin_type("O", GateType::PinType::power)); + ASSERT_TRUE(gt->assign_pin_type("I0", PinType::power)); + ASSERT_TRUE(gt->assign_pin_type("I1", PinType::power)); + ASSERT_FALSE(gt->assign_pin_type("O", PinType::power)); pin_to_type = { - {"I0", GateType::PinType::power}, - {"I1", GateType::PinType::power}, - {"O", GateType::PinType::none}}; + {"I0", PinType::power}, + {"I1", PinType::power}, + {"O", PinType::none}}; EXPECT_EQ(gt->get_pin_types(), pin_to_type); - EXPECT_EQ(gt->get_pins_of_type(GateType::PinType::power), in_pins); - EXPECT_EQ(gt->get_pins_of_type(GateType::PinType::none), out_pins); - EXPECT_EQ(gt->get_pin_type("I0"), GateType::PinType::power); - EXPECT_EQ(gt->get_pin_type("I1"), GateType::PinType::power); - EXPECT_EQ(gt->get_pin_type("O"), GateType::PinType::none); + EXPECT_EQ(gt->get_pins_of_type(PinType::power), in_pins); + EXPECT_EQ(gt->get_pins_of_type(PinType::none), out_pins); + EXPECT_EQ(gt->get_pin_type("I0"), PinType::power); + EXPECT_EQ(gt->get_pin_type("I1"), PinType::power); + EXPECT_EQ(gt->get_pin_type("O"), PinType::none); - ASSERT_TRUE(gt->assign_pin_type("I0", GateType::PinType::ground)); - ASSERT_TRUE(gt->assign_pin_type("I1", GateType::PinType::ground)); - ASSERT_FALSE(gt->assign_pin_type("O", GateType::PinType::ground)); + ASSERT_TRUE(gt->assign_pin_type("I0", PinType::ground)); + ASSERT_TRUE(gt->assign_pin_type("I1", PinType::ground)); + ASSERT_FALSE(gt->assign_pin_type("O", PinType::ground)); pin_to_type = { - {"I0", GateType::PinType::ground}, - {"I1", GateType::PinType::ground}, - {"O", GateType::PinType::none}}; + {"I0", PinType::ground}, + {"I1", PinType::ground}, + {"O", PinType::none}}; EXPECT_EQ(gt->get_pin_types(), pin_to_type); - EXPECT_EQ(gt->get_pins_of_type(GateType::PinType::ground), in_pins); - EXPECT_EQ(gt->get_pins_of_type(GateType::PinType::none), out_pins); - EXPECT_EQ(gt->get_pin_type("I0"), GateType::PinType::ground); - EXPECT_EQ(gt->get_pin_type("I1"), GateType::PinType::ground); - EXPECT_EQ(gt->get_pin_type("O"), GateType::PinType::none); + EXPECT_EQ(gt->get_pins_of_type(PinType::ground), in_pins); + EXPECT_EQ(gt->get_pins_of_type(PinType::none), out_pins); + EXPECT_EQ(gt->get_pin_type("I0"), PinType::ground); + EXPECT_EQ(gt->get_pin_type("I1"), PinType::ground); + EXPECT_EQ(gt->get_pin_type("O"), PinType::none); } // LUT pin types @@ -465,29 +465,29 @@ namespace hal GateType* gt = gl.create_gate_type("dummy2", {GateTypeProperty::lut}); ASSERT_NE(gt, nullptr); - std::unordered_map pin_to_type; + std::unordered_map pin_to_type; std::unordered_set in_pins = {"I"}; std::unordered_set out_pins = {"O"}; - EXPECT_TRUE(gt->add_pins({"I"}, GateType::PinDirection::input)); - EXPECT_TRUE(gt->add_pins({"O"}, GateType::PinDirection::output)); + EXPECT_TRUE(gt->add_pins({"I"}, PinDirection::input)); + EXPECT_TRUE(gt->add_pins({"O"}, PinDirection::output)); - EXPECT_EQ(gt->get_pin_type("I"), GateType::PinType::none); - EXPECT_EQ(gt->get_pin_type("O"), GateType::PinType::none); + EXPECT_EQ(gt->get_pin_type("I"), PinType::none); + EXPECT_EQ(gt->get_pin_type("O"), PinType::none); - ASSERT_FALSE(gt->assign_pin_type("I", GateType::PinType::lut)); - ASSERT_TRUE(gt->assign_pin_type("O", GateType::PinType::lut)); + ASSERT_FALSE(gt->assign_pin_type("I", PinType::lut)); + ASSERT_TRUE(gt->assign_pin_type("O", PinType::lut)); pin_to_type = { - {"I", GateType::PinType::none}, - {"O", GateType::PinType::lut}}; + {"I", PinType::none}, + {"O", PinType::lut}}; EXPECT_EQ(gt->get_pin_types(), pin_to_type); - EXPECT_EQ(gt->get_pins_of_type(GateType::PinType::none), in_pins); - EXPECT_EQ(gt->get_pins_of_type(GateType::PinType::lut), out_pins); - EXPECT_EQ(gt->get_pin_type("I"), GateType::PinType::none); - EXPECT_EQ(gt->get_pin_type("O"), GateType::PinType::lut); + EXPECT_EQ(gt->get_pins_of_type(PinType::none), in_pins); + EXPECT_EQ(gt->get_pins_of_type(PinType::lut), out_pins); + EXPECT_EQ(gt->get_pin_type("I"), PinType::none); + EXPECT_EQ(gt->get_pin_type("O"), PinType::lut); } // FF pin types @@ -495,55 +495,55 @@ namespace hal GateType* gt = gl.create_gate_type("dummy3", {GateTypeProperty::ff}); ASSERT_NE(gt, nullptr); - std::unordered_map pin_to_type; + std::unordered_map pin_to_type; std::unordered_set in_pins = {"I0", "I1", "I2", "I3", "I4", "I5", "I6"}; std::unordered_set out_pins = {"O0", "O1", "O2", "O3", "O4"}; - EXPECT_TRUE(gt->add_pins({"I0", "I1", "I2", "I3", "I4", "I5", "I6"}, GateType::PinDirection::input)); - EXPECT_TRUE(gt->add_pins({"O0", "O1", "O2", "O3", "O4", "O5"}, GateType::PinDirection::output)); + EXPECT_TRUE(gt->add_pins({"I0", "I1", "I2", "I3", "I4", "I5", "I6"}, PinDirection::input)); + EXPECT_TRUE(gt->add_pins({"O0", "O1", "O2", "O3", "O4", "O5"}, PinDirection::output)); for (const auto& pin : in_pins) { - EXPECT_EQ(gt->get_pin_type(pin), GateType::PinType::none); + EXPECT_EQ(gt->get_pin_type(pin), PinType::none); } for (const auto& pin : out_pins) { - EXPECT_EQ(gt->get_pin_type(pin), GateType::PinType::none); + EXPECT_EQ(gt->get_pin_type(pin), PinType::none); } - ASSERT_TRUE(gt->assign_pin_type("I0", GateType::PinType::clock)); - ASSERT_TRUE(gt->assign_pin_type("I1", GateType::PinType::enable)); - ASSERT_TRUE(gt->assign_pin_type("I2", GateType::PinType::set)); - ASSERT_TRUE(gt->assign_pin_type("I3", GateType::PinType::reset)); - ASSERT_TRUE(gt->assign_pin_type("I4", GateType::PinType::data)); - ASSERT_TRUE(gt->assign_pin_type("I5", GateType::PinType::address)); - ASSERT_FALSE(gt->assign_pin_type("I6", GateType::PinType::state)); - ASSERT_FALSE(gt->assign_pin_type("I6", GateType::PinType::neg_state)); - ASSERT_TRUE(gt->assign_pin_type("O0", GateType::PinType::state)); - ASSERT_TRUE(gt->assign_pin_type("O1", GateType::PinType::neg_state)); - ASSERT_TRUE(gt->assign_pin_type("O2", GateType::PinType::data)); - ASSERT_TRUE(gt->assign_pin_type("O3", GateType::PinType::address)); - ASSERT_TRUE(gt->assign_pin_type("O4", GateType::PinType::clock)); - ASSERT_FALSE(gt->assign_pin_type("O5", GateType::PinType::enable)); - ASSERT_FALSE(gt->assign_pin_type("O5", GateType::PinType::set)); - ASSERT_FALSE(gt->assign_pin_type("O5", GateType::PinType::reset)); + ASSERT_TRUE(gt->assign_pin_type("I0", PinType::clock)); + ASSERT_TRUE(gt->assign_pin_type("I1", PinType::enable)); + ASSERT_TRUE(gt->assign_pin_type("I2", PinType::set)); + ASSERT_TRUE(gt->assign_pin_type("I3", PinType::reset)); + ASSERT_TRUE(gt->assign_pin_type("I4", PinType::data)); + ASSERT_TRUE(gt->assign_pin_type("I5", PinType::address)); + ASSERT_FALSE(gt->assign_pin_type("I6", PinType::state)); + ASSERT_FALSE(gt->assign_pin_type("I6", PinType::neg_state)); + ASSERT_TRUE(gt->assign_pin_type("O0", PinType::state)); + ASSERT_TRUE(gt->assign_pin_type("O1", PinType::neg_state)); + ASSERT_TRUE(gt->assign_pin_type("O2", PinType::data)); + ASSERT_TRUE(gt->assign_pin_type("O3", PinType::address)); + ASSERT_TRUE(gt->assign_pin_type("O4", PinType::clock)); + ASSERT_FALSE(gt->assign_pin_type("O5", PinType::enable)); + ASSERT_FALSE(gt->assign_pin_type("O5", PinType::set)); + ASSERT_FALSE(gt->assign_pin_type("O5", PinType::reset)); pin_to_type = { - {"I0", GateType::PinType::clock}, - {"I1", GateType::PinType::enable}, - {"I2", GateType::PinType::set}, - {"I3", GateType::PinType::reset}, - {"I4", GateType::PinType::data}, - {"I5", GateType::PinType::address}, - {"I6", GateType::PinType::none}, - {"O0", GateType::PinType::state}, - {"O1", GateType::PinType::neg_state}, - {"O2", GateType::PinType::data}, - {"O3", GateType::PinType::address}, - {"O4", GateType::PinType::clock}, - {"O5", GateType::PinType::none}}; + {"I0", PinType::clock}, + {"I1", PinType::enable}, + {"I2", PinType::set}, + {"I3", PinType::reset}, + {"I4", PinType::data}, + {"I5", PinType::address}, + {"I6", PinType::none}, + {"O0", PinType::state}, + {"O1", PinType::neg_state}, + {"O2", PinType::data}, + {"O3", PinType::address}, + {"O4", PinType::clock}, + {"O5", PinType::none}}; EXPECT_EQ(gt->get_pin_types(), pin_to_type); } @@ -661,7 +661,7 @@ namespace hal GateType* gt = gl.create_gate_type("dummy", {GateTypeProperty::ff}); ASSERT_NE(gt, nullptr); - EXPECT_EQ(gt->get_clear_preset_behavior(), std::make_pair(GateType::ClearPresetBehavior::invalid, GateType::ClearPresetBehavior::invalid)); + EXPECT_EQ(gt->get_clear_preset_behavior(), std::make_pair(GateType::ClearPresetBehavior::undef, GateType::ClearPresetBehavior::undef)); gt->set_clear_preset_behavior(GateType::ClearPresetBehavior::L, GateType::ClearPresetBehavior::H); EXPECT_EQ(gt->get_clear_preset_behavior(), std::make_pair(GateType::ClearPresetBehavior::L, GateType::ClearPresetBehavior::H)); diff --git a/tests/netlist/netlist_utils.cpp b/tests/netlist/netlist_utils.cpp index 685eb056418..02040cee8a2 100644 --- a/tests/netlist/netlist_utils.cpp +++ b/tests/netlist/netlist_utils.cpp @@ -47,35 +47,35 @@ namespace hal { std::unique_ptr lib = std::unique_ptr(new GateLibrary("dummy_path", "dummy_name")); GateType* gnd = lib->create_gate_type("GND", {GateTypeProperty::combinational, GateTypeProperty::ground}); - gnd->add_pin("O", GateType::PinDirection::output); + gnd->add_pin("O", PinDirection::output); gnd->add_boolean_function("O", BooleanFunction::from_string("0")); lib->mark_gnd_gate_type(gnd); GateType* vcc = lib->create_gate_type("VCC", {GateTypeProperty::combinational, GateTypeProperty::power}); - vcc->add_pin("O", GateType::PinDirection::output); + vcc->add_pin("O", PinDirection::output); vcc->add_boolean_function("O", BooleanFunction::from_string("1")); lib->mark_vcc_gate_type(vcc); GateType* and2 = lib->create_gate_type("AND2", {GateTypeProperty::combinational}); - and2->add_pins({"I0", "I1"}, GateType::PinDirection::input); - and2->add_pin("O", GateType::PinDirection::output); + and2->add_pins({"I0", "I1"}, PinDirection::input); + and2->add_pin("O", PinDirection::output); and2->add_boolean_function("O", BooleanFunction::from_string("I0 & I1")); GateType* lut2 = lib->create_gate_type("LUT2", {GateTypeProperty::combinational, GateTypeProperty::lut}); - lut2->add_pins({"I0", "I1"}, GateType::PinDirection::input); - lut2->add_pin("O", GateType::PinDirection::output, GateType::PinType::lut); + lut2->add_pins({"I0", "I1"}, PinDirection::input); + lut2->add_pin("O", PinDirection::output, PinType::lut); lut2->set_config_data_category("generic"); lut2->set_config_data_identifier("INIT"); GateType* lut4 = lib->create_gate_type("LUT4", {GateTypeProperty::combinational, GateTypeProperty::lut}); - lut4->add_pins({"I0", "I1", "I2", "I3"}, GateType::PinDirection::input); - lut4->add_pin("O", GateType::PinDirection::output, GateType::PinType::lut); + lut4->add_pins({"I0", "I1", "I2", "I3"}, PinDirection::input); + lut4->add_pin("O", PinDirection::output, PinType::lut); lut4->set_config_data_category("generic"); lut4->set_config_data_identifier("INIT"); GateType* buf = lib->create_gate_type("BUF", {GateTypeProperty::combinational}); - buf->add_pin("I", GateType::PinDirection::input); - buf->add_pin("O", GateType::PinDirection::output); + buf->add_pin("I", PinDirection::input); + buf->add_pin("O", PinDirection::output); buf->add_boolean_function("O", BooleanFunction::from_string("I")); return std::move(lib); From b48244a24b8fcddafc2786f9c8306d741ad6020f Mon Sep 17 00:00:00 2001 From: SJulianS Date: Tue, 2 Mar 2021 12:08:18 +0100 Subject: [PATCH 2/5] cleanup --- CHANGELOG.md | 6 ++++-- .../hal_core/netlist/gate_library/gate_type.h | 18 ------------------ 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3174fd91811..c41021911b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * changed function `get_base_type` of class `GateType` to `get_properties` * changed HGL gate libraries to support multiple properties * changed function `create_gate_type` of class `GateLibrary` to support multiple properties -* added `sequential`, `power`, `ground`, `buffer`, `mux`, and `carry` base types to class `GateType` +* added `sequential`, `power`, `ground`, `buffer`, `mux`, and `carry` gate type properties to enum `GateTypeProperty` +* moved enums `PinType` and `PinDirection` from class `GateType` into global scope * added `get_path` to `netlist_utils` to retrieve all gates on the predecessor/successor path from a start gate/net to gates of a specified property * made `optimize_constants` of class `BooleanFunction` publicly accessible * refined buffer removal in `netlist_utils::remove_buffers` to take constant `0` and `1` inputs into account @@ -20,7 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * disabled extended logging again * fixed crash related to GraphicsScene destructor * fixed overlapping gates in cone view (and subsequent segfault) by suppressing gate coordinates when adding to cone view -* fixed crash caused when gate pointer cannot be found in netlist (but in module) +* fixed `get_gate_by_id` and `get_gates` of class `Netlist` returning only gates contained within one of its modules (causing a GUI crash upon deleting gates from a module) +* fixed nets of old module not updating when moving gate from one module to another ## [3.2.5] - 2021-01-29 13:15:00+02:00 (urgency: medium) * **WARNING:** temporarily enabled extended logging (includes taking screenshots) for university course purposes. Note that no data leaves your machine unless you actively provide it to us. diff --git a/include/hal_core/netlist/gate_library/gate_type.h b/include/hal_core/netlist/gate_library/gate_type.h index 9403d348491..484ac383d6f 100644 --- a/include/hal_core/netlist/gate_library/gate_type.h +++ b/include/hal_core/netlist/gate_library/gate_type.h @@ -171,24 +171,6 @@ namespace hal */ friend std::ostream& operator<<(std::ostream& os, const GateType& gate_type); - /** - * Insert the pin direction string representation to an output stream. - * - * @param[in] os - The output stream. - * @param[in] direction - The pin direction. - * @returns An output stream. - */ - friend std::ostream& operator<<(std::ostream& os, PinDirection direction); - - /** - * Insert the pin type string representation to an output stream. - * - * @param[in] os - The output stream. - * @param[in] pin_type - The pin type. - * @returns An output stream. - */ - friend std::ostream& operator<<(std::ostream& os, PinType pin_type); - /** * Check whether two gate types are equal. * From 8bf0ae92c03f648c065ab472b0fb48df2fdf9cc9 Mon Sep 17 00:00:00 2001 From: SJulianS Date: Tue, 2 Mar 2021 15:28:39 +0100 Subject: [PATCH 3/5] some enum cleanup --- include/hal_core/netlist/boolean_function.h | 11 ++++-- include/hal_core/utilities/enums.h | 1 + src/netlist/boolean_function.cpp | 41 +++++++++------------ tests/netlist/boolean_function.cpp | 10 +++++ 4 files changed, 37 insertions(+), 26 deletions(-) diff --git a/include/hal_core/netlist/boolean_function.h b/include/hal_core/netlist/boolean_function.h index 65f9951a888..b5e57aa476d 100644 --- a/include/hal_core/netlist/boolean_function.h +++ b/include/hal_core/netlist/boolean_function.h @@ -24,6 +24,7 @@ #pragma once #include "hal_core/defines.h" +#include "hal_core/utilities/enums.h" #include "z3++.h" #include @@ -48,9 +49,10 @@ namespace hal */ enum Value { - X = -1, /**< Represents an undefined value. */ - ZERO = 0, /**< Represents a logical 0. */ - ONE = 1 /**< Represents a logical 1 */ + ZERO = 0, /**< Represents a logical 0. */ + ONE = 1, /**< Represents a logical 1 */ + Z, /**< Represents an undefined value. */ + X /**< Represents an undefined value. */ }; /** @@ -388,4 +390,7 @@ namespace hal operation m_op; std::vector m_operands; }; + + template<> + std::vector EnumStrings::data; } // namespace hal diff --git a/include/hal_core/utilities/enums.h b/include/hal_core/utilities/enums.h index f58e03235fc..3603cd7b985 100644 --- a/include/hal_core/utilities/enums.h +++ b/include/hal_core/utilities/enums.h @@ -3,6 +3,7 @@ #include "hal_core/defines.h" #include +#include namespace hal { diff --git a/src/netlist/boolean_function.cpp b/src/netlist/boolean_function.cpp index 5b3178a34d2..7afa415a55f 100644 --- a/src/netlist/boolean_function.cpp +++ b/src/netlist/boolean_function.cpp @@ -8,6 +8,9 @@ namespace hal { + template<> + std::vector EnumStrings::data = {"0", "1", "Z", "X"}; + std::string BooleanFunction::to_string(const operation& op) { switch (op) @@ -30,15 +33,7 @@ namespace hal std::string BooleanFunction::to_string(Value v) { - switch (v) - { - case Value::ONE: - return "1"; - case Value::ZERO: - return "0"; - default: - return "X"; - } + return enum_to_string(v); } std::ostream& operator<<(std::ostream& os, BooleanFunction::Value v) @@ -156,7 +151,7 @@ namespace hal for (u32 i = 1; i < m_operands.size(); ++i) { // early exit - if ((m_op == operation::AND && result == 0) || (m_op == operation::OR && result == 1) || (m_op == operation::XOR && result == X)) + if ((m_op == operation::AND && result == ZERO) || (m_op == operation::OR && result == ONE) || (m_op == operation::XOR && result == X)) { break; } @@ -164,29 +159,29 @@ namespace hal auto next = m_operands[i].evaluate(inputs); if (m_op == operation::AND) { - if (next == 0 || result == 0) + if (next == ZERO || result == ZERO) { - result = (Value)0; + result = ZERO; } - else if (next == X && result == 1) + else if (next == X && result == ONE) { result = X; } } else if (m_op == operation::OR) { - if (next == 1 || result == 1) + if (next == ONE || result == ONE) { - result = (Value)1; + result = ONE; } - else if (next == X && result == 0) + else if (next == X && result == ZERO) { result = X; } } else if (m_op == operation::XOR) { - if (next == 1) + if (next == ONE) { result = (Value)(1 - result); } @@ -200,13 +195,13 @@ namespace hal if (m_invert) { - if (result == 1) + if (result == ONE) { - return (Value)0; + return ZERO; } - else if (result == 0) + else if (result == ZERO) { - return (Value)1; + return ONE; } } return result; @@ -1186,7 +1181,7 @@ namespace hal result = BooleanFunction(); - for (auto it = terms.rbegin(); it != terms.rend(); ++it) //qmc reverses order, so iterate in reverse + for (auto it = terms.begin(); it != terms.end(); ++it) { auto& term = (*it); BooleanFunction tmp; @@ -1352,7 +1347,7 @@ namespace hal { no_change = false; add_to_output(it.second[0]); - break; // 'add_to_output' invalidates table iterator, so break and restart in next iteration + break; // 'add_to_output' invalidates table iterator, so break and restart in next iteration } } diff --git a/tests/netlist/boolean_function.cpp b/tests/netlist/boolean_function.cpp index 5fffeb681e4..52ce5cbbdce 100644 --- a/tests/netlist/boolean_function.cpp +++ b/tests/netlist/boolean_function.cpp @@ -186,6 +186,16 @@ namespace hal { TEST_END } + /** + * Testing the integer values for enum BooleanFunction::Value. + */ + TEST_F(BooleanFunctionTest, check_enum_values) { + TEST_START + EXPECT_EQ(static_cast(0), BooleanFunction::Value::ZERO); + EXPECT_EQ(static_cast(1), BooleanFunction::Value::ONE); + TEST_END + } + /** * Testing the functions is_constant_one and is_constant_zero, by passing some sample inputs * From 4a8249e4f177355bacbf59e022bab07e2d559c17 Mon Sep 17 00:00:00 2001 From: SJulianS Date: Tue, 2 Mar 2021 15:45:03 +0100 Subject: [PATCH 4/5] some basic support for high impedance states --- src/netlist/boolean_function.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/netlist/boolean_function.cpp b/src/netlist/boolean_function.cpp index 7afa415a55f..4d68de5fe6a 100644 --- a/src/netlist/boolean_function.cpp +++ b/src/netlist/boolean_function.cpp @@ -163,7 +163,7 @@ namespace hal { result = ZERO; } - else if (next == X && result == ONE) + else if ((next == X || next == Z) && result == ONE) { result = X; } @@ -174,7 +174,7 @@ namespace hal { result = ONE; } - else if (next == X && result == ZERO) + else if ((next == X || next == Z) && result == ZERO) { result = X; } @@ -185,7 +185,7 @@ namespace hal { result = (Value)(1 - result); } - else if (next == X) + else if (next == X || next == Z) { result = X; } @@ -203,6 +203,10 @@ namespace hal { return ONE; } + else if (result == Z) + { + result = X; + } } return result; } @@ -300,6 +304,10 @@ namespace hal { return BooleanFunction(X); } + else if (expression == "Z") + { + return BooleanFunction(Z); + } else { // check for variable From ae134e3a5f474aa03658ec2a34324797b50a27d3 Mon Sep 17 00:00:00 2001 From: SJulianS Date: Tue, 2 Mar 2021 15:52:36 +0100 Subject: [PATCH 5/5] changelog update --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c41021911b7..7ae11119d01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,9 +16,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * added `get_path` to `netlist_utils` to retrieve all gates on the predecessor/successor path from a start gate/net to gates of a specified property * made `optimize_constants` of class `BooleanFunction` publicly accessible * refined buffer removal in `netlist_utils::remove_buffers` to take constant `0` and `1` inputs into account -* changes to `z3_utils` (WIP) +* added high-impedance state `Z` to class `BooleanFunction` and added basic support to `evaluate` * cleaned up and refined some logger outputs and streamlined log channel names * disabled extended logging again +* changes to `z3_utils` (WIP) * fixed crash related to GraphicsScene destructor * fixed overlapping gates in cone view (and subsequent segfault) by suppressing gate coordinates when adding to cone view * fixed `get_gate_by_id` and `get_gates` of class `Netlist` returning only gates contained within one of its modules (causing a GUI crash upon deleting gates from a module)