/*
 * 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_list.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::printf("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::printf("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::printf_warning(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::printf_warning(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");
            }

            //We can not determine if a .subckt is a constant generator until all
            //it's inputs have been created. So we identify them now, once the full
            //model has been defined
            mark_constant_generator_subckts();

            //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);

            curr_model().merge_nets(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;
        }

        //Marks all constant subckt generator output pins as constants
        void mark_constant_generator_subckts() {
            size_t num_blocks_marked;

            //It is possible that by marking one constant generator
            //it may 'reveal' another constant generator downstream.
            //As a result we iteratively mark constant generators until
            //no additional ones are identified.
            std::unordered_set<AtomBlockId> marked_blocks;
            do {
                num_blocks_marked = 0;

                //Look through all the blocks marking those that are
                //constant generataors
                for(auto blk_id : curr_model().blocks()) {
                    if(marked_blocks.count(blk_id)) continue; //Don't mark multiple times

                    if(curr_model().block_type(blk_id) != AtomBlockType::BLOCK) continue; //Don't mark I/Os as constants

                    if(identify_candidate_constant_generator_subckt(blk_id)) {
                        //This block is a constant generator
                        marked_blocks.insert(blk_id);

                        vtr::printf("Inferred black-box constant generator '%s'\n", 
                                    curr_model().block_name(blk_id).c_str());

                        //Mark all the output pins as constants
                        for(auto pin_id : curr_model().block_output_pins(blk_id)) {
                            curr_model().set_pin_is_constant(pin_id, true);
                        }

                        ++num_blocks_marked;
                    }
                }
            } while(num_blocks_marked != 0);
        }

        //Determines if a particular block satisfies all the criteria of a constant
        //generator.
        //
        //Returns true, if the block is a constant generator and should be marked
        bool identify_candidate_constant_generator_subckt(AtomBlockId blk_id) {
            const t_model* arch_model = curr_model().block_model(blk_id);

            //We look for combinational blocks which are not .names (i.e.
            //combinational .subckts)
            if(curr_model().block_is_combinational(blk_id)
               && arch_model->name != std::string(MODEL_NAMES)) {

                //A subckt is a constant generator if all its input nets are either:
                //  1) Constant nets (i.e. driven by constant pins), or
                //  2) Disconnected
                for(auto pin_id : curr_model().block_input_pins(blk_id)) {
                    auto net_id = curr_model().pin_net(pin_id);

                    if(net_id && !curr_model().net_is_constant(net_id)) {
                        return false;
                    } else {
                        VTR_ASSERT(!net_id || curr_model().net_is_constant(net_id));
                    }
                }
                //This subckt is a constant generator
                return true;
            }
            return false;
        }

        //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_;
        }

    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_;

        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(const 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;
}

