/*
 * BLIF Netlist Loader
 * ===================
 *
 * This loader handles loading a post-technology mapping fully flattened (i.e not
 * hierarchical) netlist in Berkely Logic Interchange Format (BLIF) file, and
 * builds a netlist data structure (AtomNetlist) from it.
 *
 * BLIF text parsing is handled by the blifparse library, while this file is responsible
 * for creating the netlist data structure.
 *
 * The main object of interest is the BlifAllocCallback struct, which implements the
 * blifparse callback interface.  The callback methods are then called when basic blif
 * primitives are encountered by the parser.  The callback methods then create the associated
 * netlist data structures.
 *
 */
#include <cstdio>
#include <cstring>
#include <ctime>
#include <sstream>
#include <unordered_set>
#include <cctype> //std::isdigit
using namespace std;

#include "blifparse.hpp"
#include "atom_netlist.h"

#include "vtr_assert.h"
#include "vtr_util.h"
#include "vtr_log.h"
#include "vtr_logic.h"
#include "vtr_time.h"
#include "vtr_digest.h"

#include "vpr_types.h"
#include "vpr_error.h"
#include "globals.h"
#include "read_blif.h"
#include "arch_types.h"
#include "echo_files.h"
#include "hash.h"

vtr::LogicValue to_vtr_logic_value(blifparse::LogicValue);

struct BlifAllocCallback : public blifparse::Callback {
    public:
        BlifAllocCallback(e_circuit_format blif_format, AtomNetlist& main_netlist, 
                          const std::string netlist_id, 
                          const t_model* user_models, const t_model* library_models)
            : main_netlist_(main_netlist)
            , netlist_id_(netlist_id)
            , user_arch_models_(user_models)
            , library_arch_models_(library_models)
            , blif_format_(blif_format) {
            VTR_ASSERT(blif_format_ == e_circuit_format::BLIF
                       || blif_format_ == e_circuit_format::EBLIF);
        }

        static constexpr const char* OUTPAD_NAME_PREFIX = "out:";

    public: //Callback interface
        void start_parse() override {}

        void finish_parse() override {
            //When parsing is finished we *move* the main netlist
            //into the user object. This ensures we never have two copies
            //(consuming twice the memory).
            size_t main_netlist_idx = determine_main_netlist_index();
            main_netlist_ = std::move(blif_models_[main_netlist_idx]);
        }

        void begin_model(std::string model_name) override {
            //Create a new model, and set it's name

            blif_models_.emplace_back(model_name, netlist_id_);
            blif_models_black_box_.emplace_back(false);
            ended_ = false;
            set_curr_block(AtomBlockId::INVALID()); //This statement doesn't define a block, so mark invalid
        }

        void inputs(std::vector<std::string> input_names) override {
            const t_model* blk_model = find_model(MODEL_INPUT);

            VTR_ASSERT_MSG(!blk_model->inputs, "Inpad model has an input port");
            VTR_ASSERT_MSG(blk_model->outputs, "Inpad model has no output port");
            VTR_ASSERT_MSG(blk_model->outputs->size == 1, "Inpad model has non-single-bit output port");
            VTR_ASSERT_MSG(!blk_model->outputs->next, "Inpad model has multiple output ports");

            std::string pin_name = blk_model->outputs->name;
            for(const auto& input : input_names) {
                AtomBlockId blk_id = curr_model().create_block(input, blk_model);
                AtomPortId port_id = curr_model().create_port(blk_id, blk_model->outputs);
                AtomNetId net_id = curr_model().create_net(input);
                curr_model().create_pin(port_id, 0, net_id, PinType::DRIVER);
            }
            set_curr_block(AtomBlockId::INVALID()); //This statement doesn't define a block, so mark invalid
        }

        void outputs(std::vector<std::string> output_names) override {
            const t_model* blk_model = find_model(MODEL_OUTPUT);

            VTR_ASSERT_MSG(!blk_model->outputs, "Outpad model has an output port");
            VTR_ASSERT_MSG(blk_model->inputs, "Outpad model has no input port");
            VTR_ASSERT_MSG(blk_model->inputs->size == 1, "Outpad model has non-single-bit input port");
            VTR_ASSERT_MSG(!blk_model->inputs->next, "Outpad model has multiple input ports");

            std::string pin_name = blk_model->inputs->name;
            for(const auto& output : output_names) {
                //Since we name blocks based on their drivers we need to uniquify outpad names,
                //which we do with a prefix
                AtomBlockId blk_id = curr_model().create_block(OUTPAD_NAME_PREFIX + output, blk_model);
                AtomPortId port_id = curr_model().create_port(blk_id, blk_model->inputs);
                AtomNetId net_id = curr_model().create_net(output);
                curr_model().create_pin(port_id, 0, net_id, PinType::SINK);
            }
            set_curr_block(AtomBlockId::INVALID()); //This statement doesn't define a block, so mark invalid
        }

        void names(std::vector<std::string> nets, std::vector<std::vector<blifparse::LogicValue>> so_cover) override {
            const t_model* blk_model = find_model(MODEL_NAMES);

            VTR_ASSERT_MSG(nets.size() > 0, "BLIF .names has no connections");

            VTR_ASSERT_MSG(blk_model->inputs, ".names model has no input port");
            VTR_ASSERT_MSG(!blk_model->inputs->next, ".names model has multiple input ports");
            if (static_cast<int>(nets.size()) - 1 > blk_model->inputs->size) {
                vpr_throw(VPR_ERROR_BLIF_F, filename_.c_str(), lineno_, "BLIF .names input size (%zu) greater than .names model input size (%d)",
                            nets.size() - 1, blk_model->inputs->size);
            }

            VTR_ASSERT_MSG(blk_model->outputs, ".names has no output port");
            VTR_ASSERT_MSG(!blk_model->outputs->next, ".names model has multiple output ports");
            VTR_ASSERT_MSG(blk_model->outputs->size == 1, ".names model has non-single-bit output");

            //Convert the single-output cover to a netlist truth table
            AtomNetlist::TruthTable truth_table;
            for(const auto& row : so_cover) {
                truth_table.emplace_back();
                for(auto val : row) {
                    truth_table[truth_table.size()-1].push_back(to_vtr_logic_value(val));
                }
            }

            AtomBlockId blk_id = curr_model().create_block(nets[nets.size()-1], blk_model, truth_table);
            set_curr_block(blk_id);

            //Create inputs
            AtomPortId input_port_id = curr_model().create_port(blk_id, blk_model->inputs);
            for(size_t i = 0; i < nets.size() - 1; ++i) {
                AtomNetId net_id = curr_model().create_net(nets[i]);

                curr_model().create_pin(input_port_id, i, net_id, PinType::SINK);
            }

            //Figure out if the output is a constant generator
            bool output_is_const = false;
            if(truth_table.empty()
                || (truth_table.size() == 1 && truth_table[0].size() == 1 && truth_table[0][0] == vtr::LogicValue::FALSE)) {
                //An empty truth table in BLIF corresponds to a constant-zero
                //  e.g.
                //
                //  #gnd is a constant 0 generator
                //  .names gnd
                //
                //An single entry truth table with value '0' also corresponds to a constant-zero
                //  e.g.
                //
                //  #gnd2 is a constant 0 generator
                //  .names gnd2
                //  0
                //
                output_is_const = true;
                VTR_LOG("Found constant-zero generator '%s'\n", nets[nets.size()-1].c_str());
            } else if(truth_table.size() == 1 && truth_table[0].size() == 1 && truth_table[0][0] == vtr::LogicValue::TRUE) {
                //A single-entry truth table with value '1' in BLIF corresponds to a constant-one
                //  e.g.
                //
                //  #vcc is a constant 1 generator
                //  .names vcc
                //  1
                //
                output_is_const = true;
                VTR_LOG("Found constant-one generator '%s'\n", nets[nets.size()-1].c_str());
            }

            //Create output
            AtomNetId net_id = curr_model().create_net(nets[nets.size()-1]);
            AtomPortId output_port_id = curr_model().create_port(blk_id, blk_model->outputs);
            curr_model().create_pin(output_port_id, 0, net_id, PinType::DRIVER, output_is_const);
        }

        void latch(std::string input, std::string output, blifparse::LatchType type, std::string control, blifparse::LogicValue init) override {
            if(type == blifparse::LatchType::UNSPECIFIED) {
                VTR_LOGF_WARN(filename_.c_str(), lineno_, "Treating latch '%s' of unspecified type as rising edge triggered\n", output.c_str());
            } else if(type != blifparse::LatchType::RISING_EDGE) {
                vpr_throw(VPR_ERROR_BLIF_F, filename_.c_str(), lineno_, "Only rising edge latches supported\n");
            }

            if (control.empty()) {
                vpr_throw(VPR_ERROR_BLIF_F, filename_.c_str(), lineno_, "Latch must have a clock\n");
            }

            const t_model* blk_model = find_model(MODEL_LATCH);

            VTR_ASSERT_MSG(blk_model->inputs, "Has one input port");
            VTR_ASSERT_MSG(blk_model->inputs->next, "Has two input port");
            VTR_ASSERT_MSG(!blk_model->inputs->next->next, "Has no more than two input port");
            VTR_ASSERT_MSG(blk_model->outputs, "Has one output port");
            VTR_ASSERT_MSG(!blk_model->outputs->next, "Has no more than one input port");

            const t_model_ports* d_model_port = blk_model->inputs;
            const t_model_ports* clk_model_port = blk_model->inputs->next;
            const t_model_ports* q_model_port = blk_model->outputs;

            VTR_ASSERT(d_model_port->name == std::string("D"));
            VTR_ASSERT(clk_model_port->name == std::string("clk"));
            VTR_ASSERT(q_model_port->name == std::string("Q"));
            VTR_ASSERT(d_model_port->size == 1);
            VTR_ASSERT(clk_model_port->size == 1);
            VTR_ASSERT(q_model_port->size == 1);
            VTR_ASSERT(clk_model_port->is_clock);

            //We set the initital value as a single entry in the 'truth_table' field
            AtomNetlist::TruthTable truth_table(1);
            truth_table[0].push_back(to_vtr_logic_value(init));

            AtomBlockId blk_id = curr_model().create_block(output, blk_model, truth_table);
            set_curr_block(blk_id);

            //The input
            AtomPortId d_port_id = curr_model().create_port(blk_id, d_model_port);
            AtomNetId d_net_id = curr_model().create_net(input);
            curr_model().create_pin(d_port_id, 0, d_net_id, PinType::SINK);

            //The output
            AtomPortId q_port_id = curr_model().create_port(blk_id, q_model_port);
            AtomNetId q_net_id = curr_model().create_net(output);
            curr_model().create_pin(q_port_id, 0, q_net_id, PinType::DRIVER);

            //The clock
            AtomPortId clk_port_id = curr_model().create_port(blk_id, clk_model_port);
            AtomNetId clk_net_id = curr_model().create_net(control);
            curr_model().create_pin(clk_port_id, 0, clk_net_id, PinType::SINK);
        }

        void subckt(std::string subckt_model, std::vector<std::string> ports, std::vector<std::string> nets) override {
            VTR_ASSERT(ports.size() == nets.size());

            const t_model* blk_model = find_model(subckt_model);

            //We name the subckt based on the net it's first output pin drives
            std::string subckt_name;
            for(size_t i = 0; i < ports.size(); ++i) {
                const t_model_ports* model_port = find_model_port(blk_model, ports[i]);
                VTR_ASSERT(model_port);

                if(model_port->dir == OUT_PORT) {
                    subckt_name = nets[i];
                    break;
                }
            }

            if(subckt_name.empty()) {
                //We need to name the block uniquely ourselves since there is no connected output
                subckt_name = unique_subckt_name();

                //Since this is unusual, warn the user
                VTR_LOGF_WARN(filename_.c_str(), lineno_,
                        "Subckt of type '%s' at %s:%d has no output pins, and has been named '%s'\n",
                        blk_model->name, filename_.c_str(), lineno_, subckt_name.c_str());
            }

            //The name for every block should be unique, check that there is no name conflict
            AtomBlockId blk_id = curr_model().find_block(subckt_name);
            if(blk_id) {
                const t_model* conflicting_model = curr_model().block_model(blk_id);
                vpr_throw(VPR_ERROR_BLIF_F, filename_.c_str(), lineno_,
                          "Duplicate blocks named '%s' found in netlist."
                          " Existing block of type '%s' conflicts with subckt of type '%s'.",
                          subckt_name.c_str(), conflicting_model->name, subckt_model.c_str());
            }

            //Create the block
            blk_id = curr_model().create_block(subckt_name, blk_model);
            set_curr_block(blk_id);

            for(size_t i = 0; i < ports.size(); ++i) {
                //Check for consistency between model and ports
                const t_model_ports* model_port = find_model_port(blk_model, ports[i]);
                VTR_ASSERT(model_port);

                //Determine the pin type
                PinType pin_type = PinType::SINK;
                if(model_port->dir == OUT_PORT) {
                    pin_type = PinType::DRIVER;
				} else {
                    VTR_ASSERT_MSG(model_port->dir == IN_PORT, "Unexpected port type");
                }

                //Make the port
                std::string port_base;
                size_t port_bit;
                std::tie(port_base, port_bit) = split_index(ports[i]);

                AtomPortId port_id = curr_model().create_port(blk_id, find_model_port(blk_model, port_base));

                //Make the net
                AtomNetId net_id = curr_model().create_net(nets[i]);

                //Make the pin
                curr_model().create_pin(port_id, port_bit, net_id, pin_type);
            }
        }

        void blackbox() override {
            //We treat black-boxes as netlists during parsing so they should contain
            //only inpads/outpads
            for(const auto& blk_id : curr_model().blocks()) {
                auto blk_type = curr_model().block_type(blk_id);
                if(!(blk_type == AtomBlockType::INPAD || blk_type == AtomBlockType::OUTPAD)) {
                    vpr_throw(VPR_ERROR_BLIF_F, filename_.c_str(), lineno_, "Unexpected primitives in blackbox model");
                }
            }
            set_curr_model_blackbox(true);
            set_curr_block(AtomBlockId::INVALID()); //This statement doesn't define a block, so mark invalid
        }

        void end_model() override {
            if(ended_) {
                vpr_throw(VPR_ERROR_BLIF_F, filename_.c_str(), lineno_, "Unexpected .end");
            }

            merge_conn_nets();

            //Mark as ended
            ended_ = true;

            set_curr_block(AtomBlockId::INVALID()); //This statement doesn't define a block, so mark invalid
        }

        //BLIF Extensions
        void conn(std::string src, std::string dst) override {
            if (blif_format_ != e_circuit_format::EBLIF) {
                parse_error(lineno_, ".conn", "Supported only in extended BLIF format");
            }

            //We allow the .conn to create the nets if they don't exist,
            //however typically they will have already been defined.
            AtomNetId driver_net = curr_model().create_net(src);
            AtomNetId sink_net = curr_model().create_net(dst);

            //We eventually need to merge the driver and sink nets,
            //however we must defer that until all the net drivers 
            //and sinks have been created (otherwise they may not 
            //be properly merged depending on where the .conn is
            //delcared).
            //
            //As a result we record the nets to merge and do the actual merging at
            //the end of the .model
            curr_nets_to_merge_.emplace_back(driver_net, sink_net);

            set_curr_block(AtomBlockId::INVALID());
        }

        void cname(std::string cell_name) override {
            if (blif_format_ != e_circuit_format::EBLIF) {
                parse_error(lineno_, ".cname", "Supported only in extended BLIF format");
            }

            //Re-name the block
            curr_model().set_block_name(curr_block(), cell_name);
        }

        void attr(std::string name, std::string value) override {
            if (blif_format_ != e_circuit_format::EBLIF) {
                parse_error(lineno_, ".attr", "Supported only in extended BLIF format");
            }

            curr_model().set_block_attr(curr_block(), name, value);
        }

        void param(std::string name, std::string value) override {
            if (blif_format_ != e_circuit_format::EBLIF) {
                parse_error(lineno_, ".param", "Supported only in extended BLIF format");
            }

            curr_model().set_block_param(curr_block(), name, value);
        }



        //Utilities
        void filename(std::string fname) override { filename_ = fname; }

        void lineno(int line_num) override { lineno_ = line_num; }

        void parse_error(const int curr_lineno, const std::string& near_text, const std::string& msg) override {
            vpr_throw(VPR_ERROR_BLIF_F, filename_.c_str(), curr_lineno,
                    "Error in blif file near '%s': %s\n", near_text.c_str(), msg.c_str());
        }
    public:
        //Retrieve the netlist
        size_t determine_main_netlist_index() {
            //Look through all the models loaded, to find the one which is non-blackbox (i.e. has real blocks
            //and is not a blackbox).  To check for errors we look at all models, even if we've already
            //found a non-blackbox model.
            int top_model_idx = -1; //Not valid

            for(int i = 0; i < static_cast<int>(blif_models_.size()); ++i) {
                if(!blif_models_black_box_[i]) {
                    //A non-blackbox model
                    if(top_model_idx == -1) {
                        //This is the top model
                        top_model_idx = i;
                    } else {
                        //We already have a top model
                        vpr_throw(VPR_ERROR_BLIF_F, filename_.c_str(), lineno_,
                                "Found multiple models with primitives. "
                                "Only one model can contain primitives, the others must be blackboxes.");
                    }
                } else {
                    //Verify blackbox models match the architecture
                    verify_blackbox_model(blif_models_[i]);
                }
            }

            if(top_model_idx == -1) {
                vpr_throw(VPR_ERROR_BLIF_F, filename_.c_str(), lineno_,
                        "No non-blackbox models found. The main model must not be a blackbox.");
            }

            //Return the main model
            VTR_ASSERT(top_model_idx >= 0);
            return static_cast<size_t>(top_model_idx);
        }

    private:
        const t_model* find_model(std::string name) {
            const t_model* arch_model = nullptr;
            for(const t_model* arch_models : {user_arch_models_, library_arch_models_}) {
                arch_model = arch_models;
                while(arch_model) {
                    if(name == arch_model->name) {
                        //Found it
                        break;
                    }
                    arch_model = arch_model->next;
                }
                if(arch_model) {
                    //Found it
                    break;
                }
            }
            if(!arch_model) {
                vpr_throw(VPR_ERROR_BLIF_F, filename_.c_str(), lineno_, "Failed to find matching architecture model for '%s'\n",
                          name.c_str());
            }
            return arch_model;
        }

        const t_model_ports* find_model_port(const t_model* blk_model, std::string port_name) {
            //We need to handle both single, and multi-bit port names
            //
            //By convention multi-bit port names have the bit index stored in square brackets
            //at the end of the name. For example:
            //
            //   my_signal_name[2]
            //
            //indicates the 2nd bit of the port 'my_signal_name'.
            std::string trimmed_port_name;
            int bit_index;

            //Extract the index bit
            std::tie(trimmed_port_name, bit_index) = split_index(port_name);

            //We now have the valid bit index and port_name is the name excluding the index info
            VTR_ASSERT(bit_index >= 0);

            //We now look through all the ports on the model looking for the matching port
            for(const t_model_ports* ports : {blk_model->inputs, blk_model->outputs}) {

                const t_model_ports* curr_port = ports;
                while(curr_port) {
                    if(trimmed_port_name == curr_port->name) {
                        //Found a matching port, we need to verify the index
                        if(bit_index < curr_port->size) {
                            //Valid port index
                            return curr_port;
                        } else {
                            //Out of range
                            vpr_throw(VPR_ERROR_BLIF_F, filename_.c_str(), lineno_,
                                     "Port '%s' on architecture model '%s' exceeds port width (%d bits)\n",
                                      port_name.c_str(), blk_model->name, curr_port->size);
                        }
                    }
                    curr_port = curr_port->next;
                }
            }

            //No match
            vpr_throw(VPR_ERROR_BLIF_F, filename_.c_str(), lineno_,
                     "Found no matching port '%s' on architecture model '%s'\n",
                      port_name.c_str(), blk_model->name);
            return nullptr;
        }

        //Splits the index off a signal name and returns the base signal name (excluding
        //the index) and the index as an integer. For example
        //
        //  "my_signal_name[2]"   -> "my_signal_name", 2
        std::pair<std::string, int> split_index(const std::string& signal_name) {
            int bit_index = 0;

            std::string trimmed_signal_name = signal_name;

            auto iter = --signal_name.end(); //Initialized to the last char
            if(*iter == ']') {
                //The name may end in an index
                //
                //To verify, we iterate back through the string until we find
                //an open square brackets, or non digit character
                --iter; //Advance past ']'
                while(iter != signal_name.begin() && std::isdigit(*iter)) --iter;

                //We are at the first non-digit character from the end (or the beginning of the string)
                if(*iter == '[') {
                    //We have a valid index in the open range (iter, --signal_name.end())
                    std::string index_str(iter+1, --signal_name.end());

                    //Convert to an integer
                    std::stringstream ss(index_str);
                    ss >> bit_index;
                    VTR_ASSERT_MSG(!ss.fail() && ss.eof(), "Failed to extract signal index");

                    //Trim the signal name to exclude the final index
                    trimmed_signal_name = std::string(signal_name.begin(), iter);
                }
            }
            return std::make_pair(trimmed_signal_name, bit_index);
        }

        //Retieves a reference to the currently active .model
        AtomNetlist& curr_model() {
            if(blif_models_.empty() || ended_) {
                vpr_throw(VPR_ERROR_BLIF_F, filename_.c_str(), lineno_, "Expected .model");
            }

            return blif_models_[blif_models_.size()-1];
        }

        void set_curr_model_blackbox(bool val) {
            VTR_ASSERT(blif_models_.size() == blif_models_black_box_.size());
            blif_models_black_box_[blif_models_black_box_.size()-1] = val;
        }

        bool verify_blackbox_model(AtomNetlist& blif_model) {
            const t_model* arch_model = find_model(blif_model.netlist_name());

            //Verify each port on the model
            //
            // We parse each .model as it's own netlist so the IOs
            // get converted to blocks
            for(auto blk_id : blif_model.blocks()) {


                //Check that the port directions match
                if(blif_model.block_type(blk_id) == AtomBlockType::INPAD) {

                    const auto& input_name = blif_model.block_name(blk_id);

                    //Find model port already verifies the port widths
                    const t_model_ports* arch_model_port = find_model_port(arch_model, input_name);
                    VTR_ASSERT(arch_model_port);
                    VTR_ASSERT(arch_model_port->dir == IN_PORT);

                } else {
                    VTR_ASSERT(blif_model.block_type(blk_id) == AtomBlockType::OUTPAD);

                    auto raw_output_name = blif_model.block_name(blk_id);

                    std::string output_name = vtr::replace_first(raw_output_name, OUTPAD_NAME_PREFIX, "");

                    //Find model port already verifies the port widths
                    const t_model_ports* arch_model_port = find_model_port(arch_model, output_name);
                    VTR_ASSERT(arch_model_port);

                    VTR_ASSERT(arch_model_port->dir == OUT_PORT);
                }
            }
            return true;
        }

        //Returns a different unique subck name each time it is called
        std::string unique_subckt_name() {
            return "unnamed_subckt" + std::to_string(unique_subckt_name_counter_++);
        }

        //Sets the current block which is being processed
        // Used to determine which block a .cname, .param, .attr apply to
        void set_curr_block(AtomBlockId blk) {
            curr_block_ = blk;
        }

        //Gets the current block which is being processed
        AtomBlockId curr_block() const {
            return curr_block_;
        }

        //Merges all the recorded net pairs which need to be merged
        //
        //This should only be called at the end of a .model to ensure that
        //all the associated driver/sink pins have been delcared and connected
        //to their nets
        void merge_conn_nets() {
            for (auto net_pair : curr_nets_to_merge_) {
                curr_model().merge_nets(net_pair.first, net_pair.second);
            }

            curr_nets_to_merge_.clear();
        }

    private:
        bool ended_ = true; //Initially no active .model
        std::string filename_ = "";
        int lineno_ = -1;

        std::vector<AtomNetlist> blif_models_;
        std::vector<bool> blif_models_black_box_;

        AtomNetlist& main_netlist_; //User object we fill
        const std::string netlist_id_; //Unique identifier based on the contents of the blif file
        const t_model* user_arch_models_ = nullptr;
        const t_model* library_arch_models_ = nullptr;

        size_t unique_subckt_name_counter_ = 0;

        AtomBlockId curr_block_;
        std::vector<std::pair<AtomNetId,AtomNetId>> curr_nets_to_merge_;

        e_circuit_format blif_format_ = e_circuit_format::BLIF;

};


vtr::LogicValue to_vtr_logic_value(blifparse::LogicValue val) {
    vtr::LogicValue new_val = vtr::LogicValue::UNKOWN;
    switch(val) {
        case blifparse::LogicValue::TRUE: new_val = vtr::LogicValue::TRUE; break;
        case blifparse::LogicValue::FALSE: new_val = vtr::LogicValue::FALSE; break;
        case blifparse::LogicValue::DONT_CARE: new_val = vtr::LogicValue::DONT_CARE; break;
        case blifparse::LogicValue::UNKOWN: new_val = vtr::LogicValue::UNKOWN; break;
        default: VTR_ASSERT_OPT_MSG(false, "Unkown logic value");
    }
    return new_val;
}

AtomNetlist read_blif(e_circuit_format circuit_format,
                      const char *blif_file,
                      const t_model *user_models,
                      const t_model *library_models) {


    AtomNetlist netlist;
    std::string netlist_id = vtr::secure_digest_file(blif_file);

    BlifAllocCallback alloc_callback(circuit_format, netlist, netlist_id, user_models, library_models);
    blifparse::blif_parse_filename(blif_file, alloc_callback);

    return netlist;
}

