blob: f911f47d190626a2ee6bd64c74c4b59f34a53d98 [file] [log] [blame]
#include <algorithm>
#include <unordered_set>
#include <queue>
#include <numeric>
#include "atom_netlist.h"
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vpr_error.h"
/*
*
*
* AtomNetlist Class Implementation
*
*
*/
AtomNetlist::AtomNetlist(std::string name, std::string id)
: Netlist<AtomBlockId, AtomPortId, AtomPinId, AtomNetId>(name, id) {}
/*
*
* Blocks
*
*/
AtomBlockType AtomNetlist::block_type(const AtomBlockId id) const {
const t_model* blk_model = block_model(id);
AtomBlockType type = AtomBlockType::BLOCK;
if (blk_model->name == std::string(MODEL_INPUT)) {
type = AtomBlockType::INPAD;
} else if (blk_model->name == std::string(MODEL_OUTPUT)) {
type = AtomBlockType::OUTPAD;
} else {
type = AtomBlockType::BLOCK;
}
return type;
}
const t_model* AtomNetlist::block_model(const AtomBlockId id) const {
VTR_ASSERT_SAFE(valid_block_id(id));
return block_models_[id];
}
const AtomNetlist::TruthTable& AtomNetlist::block_truth_table(const AtomBlockId id) const {
VTR_ASSERT_SAFE(valid_block_id(id));
return block_truth_tables_[id];
}
/*
*
* Ports
*
*/
const t_model_ports* AtomNetlist::port_model(const AtomPortId id) const {
VTR_ASSERT_SAFE(valid_port_id(id));
return port_models_[id];
}
/*
*
* Lookups
*
*/
AtomPortId AtomNetlist::find_atom_port(const AtomBlockId blk_id, const t_model_ports* model_port) const {
VTR_ASSERT_SAFE(valid_block_id(blk_id));
VTR_ASSERT_SAFE(model_port);
//We can tell from the model port the set of ports
//the port can be found in
port_range range = (model_port->dir == IN_PORT) ? (model_port->is_clock) ? block_clock_ports(blk_id) : block_input_ports(blk_id)
: (block_output_ports(blk_id));
for (auto port_id : range) {
if (port_name(port_id) == model_port->name) {
return port_id;
}
}
return AtomPortId::INVALID();
}
AtomBlockId AtomNetlist::find_atom_pin_driver(const AtomBlockId blk_id, const t_model_ports* model_port, const BitIndex port_bit) const {
// find the port id the matches the given port model
AtomPortId port_id = find_atom_port(blk_id, model_port);
if (port_id) {
// if port exists, find the driving net of the given port bit
AtomNetId driving_net_id = port_net(port_id, port_bit);
if (driving_net_id) {
// if the driving net exists, find the pin driving this net
auto driver_pin_id = net_driver(driving_net_id);
// return the block id of the block associated with this pin
return pin_block(driver_pin_id);
}
}
return AtomBlockId::INVALID();
}
/*
*
* Mutators
*
*/
AtomBlockId AtomNetlist::create_block(const std::string name, const t_model* model, const TruthTable truth_table) {
AtomBlockId blk_id = Netlist::create_block(name);
//Initialize the data
block_models_.push_back(model);
block_truth_tables_.push_back(truth_table);
//Check post-conditions: size
VTR_ASSERT(validate_block_sizes());
//Check post-conditions: values
VTR_ASSERT(block_model(blk_id) == model);
VTR_ASSERT(block_truth_table(blk_id) == truth_table);
return blk_id;
}
AtomPortId AtomNetlist::create_port(const AtomBlockId blk_id, const t_model_ports* model_port) {
AtomPortId port_id = find_port(blk_id, model_port->name);
PortType type = PortType::INPUT;
//Determine the PortType
if (model_port->dir == IN_PORT) {
if (model_port->is_clock) {
type = PortType::CLOCK;
} else {
type = PortType::INPUT;
}
} else if (model_port->dir == OUT_PORT) {
type = PortType::OUTPUT;
} else {
VPR_FATAL_ERROR(VPR_ERROR_ATOM_NETLIST, "Unrecognized model port type");
}
if (!port_id) {
port_id = Netlist::create_port(blk_id, model_port->name, model_port->size, type);
port_models_.push_back(model_port);
associate_port_with_block(port_id, port_type(port_id), blk_id);
}
//Check post-conditions: size
VTR_ASSERT(validate_port_sizes());
//Check post-conditions: values
VTR_ASSERT(port_name(port_id) == model_port->name);
VTR_ASSERT(port_width(port_id) == (unsigned)model_port->size);
VTR_ASSERT(port_model(port_id) == model_port);
VTR_ASSERT(port_type(port_id) == type);
VTR_ASSERT_SAFE(find_port(blk_id, model_port->name) == port_id);
VTR_ASSERT_SAFE(find_atom_port(blk_id, model_port) == port_id);
return port_id;
}
AtomPinId AtomNetlist::create_pin(const AtomPortId port_id, BitIndex port_bit, const AtomNetId net_id, const PinType pin_type_, bool is_const) {
AtomPinId pin_id = Netlist::create_pin(port_id, port_bit, net_id, pin_type_, is_const);
//Check post-conditions: size
VTR_ASSERT(validate_pin_sizes());
VTR_ASSERT(pin_type(pin_id) == pin_type_);
VTR_ASSERT(pin_port(pin_id) == port_id);
VTR_ASSERT(pin_port_type(pin_id) == port_type(port_id));
return pin_id;
}
AtomNetId AtomNetlist::create_net(const std::string name) {
AtomNetId net_id = Netlist::create_net(name);
//Check post-conditions: size
VTR_ASSERT(validate_net_sizes());
return net_id;
}
AtomNetId AtomNetlist::add_net(const std::string name, AtomPinId driver, std::vector<AtomPinId> sinks) {
return Netlist::add_net(name, driver, sinks);
}
void AtomNetlist::remove_block_impl(const AtomBlockId /*blk_id*/) {
//Unused
}
void AtomNetlist::remove_port_impl(const AtomPortId /*port_id*/) {
//Unused
}
void AtomNetlist::remove_pin_impl(const AtomPinId /*pin_id*/) {
//Unused
}
void AtomNetlist::remove_net_impl(const AtomNetId /*net_id*/) {
//Unused
}
void AtomNetlist::rebuild_block_refs_impl(const vtr::vector_map<AtomPinId, AtomPinId>& /*pin_id_map*/,
const vtr::vector_map<AtomPortId, AtomPortId>& /*port_id_map*/) {
//Unused
}
void AtomNetlist::rebuild_port_refs_impl(const vtr::vector_map<AtomBlockId, AtomBlockId>& /*block_id_map*/,
const vtr::vector_map<AtomPinId, AtomPinId>& /*pin_id_map*/) {
//Unused
}
void AtomNetlist::rebuild_pin_refs_impl(const vtr::vector_map<AtomPortId, AtomPortId>& /*port_id_map*/,
const vtr::vector_map<AtomNetId, AtomNetId>& /*net_id_map*/) {
//Unused
}
void AtomNetlist::rebuild_net_refs_impl(const vtr::vector_map<AtomPinId, AtomPinId>& /*pin_id_map*/) {
//Unused
}
/*
*
* Internal utilities
*
*/
void AtomNetlist::clean_blocks_impl(const vtr::vector_map<AtomBlockId, AtomBlockId>& block_id_map) {
//Update all the block_models and block
block_models_ = clean_and_reorder_values(block_models_, block_id_map);
block_truth_tables_ = clean_and_reorder_values(block_truth_tables_, block_id_map);
}
void AtomNetlist::clean_ports_impl(const vtr::vector_map<AtomPortId, AtomPortId>& port_id_map) {
//Update all port_models_ values
port_models_ = clean_and_reorder_values(port_models_, port_id_map);
}
void AtomNetlist::clean_pins_impl(const vtr::vector_map<AtomPinId, AtomPinId>& /*pin_id_map*/) {
//Unused
}
void AtomNetlist::clean_nets_impl(const vtr::vector_map<AtomNetId, AtomNetId>& /*net_id_map*/) {
//Unused
}
void AtomNetlist::shrink_to_fit_impl() {
//Block data
block_models_.shrink_to_fit();
//Port data
port_models_.shrink_to_fit();
}
/*
*
* Sanity Checks
*
*/
bool AtomNetlist::validate_block_sizes_impl(size_t num_blocks) const {
if (block_truth_tables_.size() != num_blocks
|| block_models_.size() != num_blocks) {
return false;
}
return true;
}
bool AtomNetlist::validate_port_sizes_impl(size_t num_ports) const {
if (port_models_.size() != num_ports) {
return false;
}
return true;
}
bool AtomNetlist::validate_pin_sizes_impl(size_t /*num_pins*/) const {
//No atom specific pin data to check
return true;
}
bool AtomNetlist::validate_net_sizes_impl(size_t /*num_nets*/) const {
//No atom specific net data to check
return true;
}