Skip to content

Logical netlist writer #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 27 commits into
base: acom/fpga-interchange-improve-arch-reading
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9d62fc7
libs: arch: move common functions to util and check source files
acomodi Nov 29, 2021
bcb0acc
libs: arch: interchange: add logical blocks and physical tile parsing
acomodi Nov 29, 2021
944ea53
vpr: tests: improve interchange tests
acomodi Nov 29, 2021
8471bdd
libs: arch: interchange: improve bel to cell mapping
acomodi Nov 17, 2021
f5b3fb9
libs: arch: fix multiple sites and rr graph gen
acomodi Dec 3, 2021
bd84e32
libs: arch: interchange: fix IO pads reading
acomodi Dec 3, 2021
86fa279
libs: arch: interchange: add workarounds for RR graph generation
acomodi Dec 3, 2021
75bd5f8
vpr: test: interchange: fix grid width and height
acomodi Dec 3, 2021
794d96b
vpr: base: remove cStr() casts from interchange netlist reader
mtdudek Dec 6, 2021
0143004
libs: arch: interchange: fix and enhance to start reading in xc7 arch
acomodi Dec 6, 2021
254d9fc
libs: arch: interchange: allow cascading routing bels
acomodi Dec 7, 2021
acab037
vpr: pack: allow pins to have name starting with integer
acomodi Dec 7, 2021
4aa698c
libs: arch: interchange : allow inout ports in bels connected to pads
acomodi Dec 10, 2021
c040ab2
vpr: base: interchange: netlist: add c-style init and fixed bug
acomodi Dec 13, 2021
9a345ef
libs: arch: interchange: add pack pattern propagation
acomodi Dec 14, 2021
20a1e2b
libs: arch: interchange: clean and add in-code comments
acomodi Dec 15, 2021
4cfd197
vpr: test: adjust grid layout test as NULL tile is not in the grid
acomodi Dec 15, 2021
c8ab8bf
Added reading LUT elements from FPGA interchange
mkurc-ant Dec 8, 2021
21728dd
libs: arch: interchange: fix luts that have additional pins
acomodi Dec 16, 2021
2e33368
Initial writer implementation. Blind writing of cell declarations (mo…
mkurc-ant Dec 14, 2021
4198651
Reworked cell declarations, added serializing cell instances, no nets…
mkurc-ant Dec 15, 2021
60b5ee3
Added serialization of nets. Apart from possible bugs the only thing …
mkurc-ant Dec 15, 2021
9d5c34f
Added conversion of all .input/.output instances to a single top-leve…
mkurc-ant Dec 16, 2021
08dde9d
Added top-level port connections
mkurc-ant Dec 17, 2021
dd764da
Added a command line option controlling circuit netlist writeout
mkurc-ant Dec 17, 2021
22c1598
Added serialization of property maps
mkurc-ant Dec 17, 2021
0566d67
Code formatting
mkurc-ant Dec 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 207 additions & 4 deletions libs/libarchfpga/src/arch_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,9 +555,9 @@ t_port* findPortByName(const char* name, t_pb_type* pb_type, int* high_index, in
return port;
}

t_physical_tile_type SetupEmptyPhysicalType() {
t_physical_tile_type get_empty_physical_type(std::string name) {
t_physical_tile_type type;
type.name = vtr::strdup("EMPTY");
type.name = vtr::strdup(name.c_str());
type.num_pins = 0;
type.width = 1;
type.height = 1;
Expand All @@ -573,9 +573,9 @@ t_physical_tile_type SetupEmptyPhysicalType() {
return type;
}

t_logical_block_type SetupEmptyLogicalType() {
t_logical_block_type get_empty_logical_type(std::string name) {
t_logical_block_type type;
type.name = vtr::strdup("EMPTY");
type.name = vtr::strdup(name.c_str());
type.pb_type = nullptr;

return type;
Expand Down Expand Up @@ -1392,5 +1392,208 @@ const t_pin_to_pin_annotation* find_combinational_annotation(const t_pb_type* pb
}
}
}

return nullptr;
}

void link_physical_logical_types(std::vector<t_physical_tile_type>& PhysicalTileTypes,
std::vector<t_logical_block_type>& LogicalBlockTypes) {
for (auto& physical_tile : PhysicalTileTypes) {
if (physical_tile.index == EMPTY_TYPE_INDEX) continue;

auto eq_sites_set = get_equivalent_sites_set(&physical_tile);
auto equivalent_sites = std::vector<t_logical_block_type_ptr>(eq_sites_set.begin(), eq_sites_set.end());

auto criteria = [&physical_tile](const t_logical_block_type* lhs, const t_logical_block_type* rhs) {
int num_pins = physical_tile.num_inst_pins;

int lhs_num_logical_pins = lhs->pb_type->num_pins;
int rhs_num_logical_pins = rhs->pb_type->num_pins;

int lhs_diff_num_pins = num_pins - lhs_num_logical_pins;
int rhs_diff_num_pins = num_pins - rhs_num_logical_pins;

return lhs_diff_num_pins < rhs_diff_num_pins;
};

std::sort(equivalent_sites.begin(), equivalent_sites.end(), criteria);

for (auto& logical_block : LogicalBlockTypes) {
for (auto site : equivalent_sites) {
if (0 == strcmp(logical_block.name, site->pb_type->name)) {
logical_block.equivalent_tiles.push_back(&physical_tile);
break;
}
}
}
}

for (auto& logical_block : LogicalBlockTypes) {
if (logical_block.index == EMPTY_TYPE_INDEX) continue;

auto& equivalent_tiles = logical_block.equivalent_tiles;

if ((int)equivalent_tiles.size() <= 0) {
archfpga_throw(__FILE__, __LINE__,
"Logical Block %s does not have any equivalent tiles.\n", logical_block.name);
}

std::unordered_map<int, bool> ignored_pins_check_map;
std::unordered_map<int, bool> global_pins_check_map;

auto criteria = [&logical_block](const t_physical_tile_type* lhs, const t_physical_tile_type* rhs) {
int num_logical_pins = logical_block.pb_type->num_pins;

int lhs_num_pins = lhs->num_inst_pins;
int rhs_num_pins = rhs->num_inst_pins;

int lhs_diff_num_pins = lhs_num_pins - num_logical_pins;
int rhs_diff_num_pins = rhs_num_pins - num_logical_pins;

return lhs_diff_num_pins < rhs_diff_num_pins;
};

std::sort(equivalent_tiles.begin(), equivalent_tiles.end(), criteria);

for (int pin = 0; pin < logical_block.pb_type->num_pins; pin++) {
for (auto& tile : equivalent_tiles) {
auto direct_maps = tile->tile_block_pin_directs_map.at(logical_block.index);

for (auto& sub_tile : tile->sub_tiles) {
auto equiv_sites = sub_tile.equivalent_sites;
if (std::find(equiv_sites.begin(), equiv_sites.end(), &logical_block) == equiv_sites.end()) {
continue;
}

auto direct_map = direct_maps.at(sub_tile.index);

auto result = direct_map.find(t_logical_pin(pin));
if (result == direct_map.end()) {
archfpga_throw(__FILE__, __LINE__,
"Logical pin %d not present in pin mapping between Tile %s and Block %s.\n",
pin, tile->name, logical_block.name);
}

int sub_tile_pin_index = result->second.pin;
int phy_index = sub_tile.sub_tile_to_tile_pin_indices[sub_tile_pin_index];

bool is_ignored = tile->is_ignored_pin[phy_index];
bool is_global = tile->is_pin_global[phy_index];

auto ignored_result = ignored_pins_check_map.insert(std::pair<int, bool>(pin, is_ignored));
if (!ignored_result.second && ignored_result.first->second != is_ignored) {
archfpga_throw(__FILE__, __LINE__,
"Physical Tile %s has a different value for the ignored pin (physical pin: %d, logical pin: %d) "
"different from the corresponding pins of the other equivalent site %s\n.",
tile->name, phy_index, pin, logical_block.name);
}

auto global_result = global_pins_check_map.insert(std::pair<int, bool>(pin, is_global));
if (!global_result.second && global_result.first->second != is_global) {
archfpga_throw(__FILE__, __LINE__,
"Physical Tile %s has a different value for the global pin (physical pin: %d, logical pin: %d) "
"different from the corresponding pins of the other equivalent sites\n.",
tile->name, phy_index, pin);
}
}
}
}
}
}

/* Sets up the pin classes for the type. */
void setup_pin_classes(t_physical_tile_type* type) {
int i, k;
int pin_count;
int num_class;

for (i = 0; i < type->num_pins; i++) {
type->pin_class.push_back(OPEN);
type->is_ignored_pin.push_back(true);
type->is_pin_global.push_back(true);
}

pin_count = 0;

t_class_range class_range;

/* Equivalent pins share the same class, non-equivalent pins belong to different pin classes */
for (auto& sub_tile : type->sub_tiles) {
int capacity = sub_tile.capacity.total();
class_range.low = type->class_inf.size();
class_range.high = class_range.low - 1;
for (i = 0; i < capacity; ++i) {
for (const auto& port : sub_tile.ports) {
if (port.equivalent != PortEquivalence::NONE) {
t_class class_inf;
num_class = (int)type->class_inf.size();
class_inf.num_pins = port.num_pins;
class_inf.equivalence = port.equivalent;

if (port.type == IN_PORT) {
class_inf.type = RECEIVER;
} else {
VTR_ASSERT(port.type == OUT_PORT);
class_inf.type = DRIVER;
}

for (k = 0; k < port.num_pins; ++k) {
class_inf.pinlist.push_back(pin_count);
type->pin_class[pin_count] = num_class;
// clock pins and other specified global ports are initially specified
// as ignored pins (i.e. connections are not created in the rr_graph and
// nets connected to the port are ignored as well).
type->is_ignored_pin[pin_count] = port.is_clock || port.is_non_clock_global;
// clock pins and other specified global ports are flaged as global
type->is_pin_global[pin_count] = port.is_clock || port.is_non_clock_global;

if (port.is_clock) {
type->clock_pin_indices.push_back(pin_count);
}

pin_count++;
}

type->class_inf.push_back(class_inf);
class_range.high++;
} else if (port.equivalent == PortEquivalence::NONE) {
for (k = 0; k < port.num_pins; ++k) {
t_class class_inf;
num_class = (int)type->class_inf.size();
class_inf.num_pins = 1;
class_inf.pinlist.push_back(pin_count);
class_inf.equivalence = port.equivalent;

if (port.type == IN_PORT) {
class_inf.type = RECEIVER;
} else {
VTR_ASSERT(port.type == OUT_PORT);
class_inf.type = DRIVER;
}

type->pin_class[pin_count] = num_class;
// clock pins and other specified global ports are initially specified
// as ignored pins (i.e. connections are not created in the rr_graph and
// nets connected to the port are ignored as well).
type->is_ignored_pin[pin_count] = port.is_clock || port.is_non_clock_global;
// clock pins and other specified global ports are flaged as global
type->is_pin_global[pin_count] = port.is_clock || port.is_non_clock_global;

if (port.is_clock) {
type->clock_pin_indices.push_back(pin_count);
}

pin_count++;

type->class_inf.push_back(class_inf);
class_range.high++;
}
}
}
}

type->sub_tiles[sub_tile.index].class_range = class_range;
}

VTR_ASSERT(pin_count == type->num_pins);
}
8 changes: 6 additions & 2 deletions libs/libarchfpga/src/arch_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ void free_type_descriptors(std::vector<t_physical_tile_type>& type_descriptors);

t_port* findPortByName(const char* name, t_pb_type* pb_type, int* high_index, int* low_index);

t_physical_tile_type SetupEmptyPhysicalType();
t_logical_block_type SetupEmptyLogicalType();
t_physical_tile_type get_empty_physical_type(std::string name);
t_logical_block_type get_empty_logical_type(std::string name);

std::unordered_set<t_logical_block_type_ptr> get_equivalent_sites_set(t_physical_tile_type_ptr type);

Expand Down Expand Up @@ -100,4 +100,8 @@ bool pb_type_contains_blif_model(const t_pb_type* pb_type, const std::string& bl
const t_pin_to_pin_annotation* find_sequential_annotation(const t_pb_type* pb_type, const t_model_ports* port, enum e_pin_to_pin_delay_annotations annot_type);
const t_pin_to_pin_annotation* find_combinational_annotation(const t_pb_type* pb_type, std::string in_port, std::string out_port);

void link_physical_logical_types(std::vector<t_physical_tile_type>& PhysicalTileTypes,
std::vector<t_logical_block_type>& LogicalBlockTypes);

void setup_pin_classes(t_physical_tile_type* type);
#endif
23 changes: 23 additions & 0 deletions libs/libarchfpga/src/physical_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1738,9 +1738,31 @@ struct t_lut_cell {
std::vector<std::string> inputs;
};

struct t_lut_bel {
std::string name;

std::vector<std::string> input_pins;
std::string output_pin;

bool operator==(const t_lut_bel& other) const {
return name == other.name && input_pins == other.input_pins && output_pin == other.output_pin;
}
};

struct t_lut_element {
std::string site_type;
int width;
std::vector<t_lut_bel> lut_bels;

bool operator==(const t_lut_element& other) const {
return site_type == other.site_type && width == other.width && lut_bels == other.lut_bels;
}
};

/* Detailed routing architecture */
struct t_arch {
mutable vtr::string_internment strings;
std::vector<vtr::interned_string> interned_strings;

char* architecture_id; //Secure hash digest of the architecture file to uniquely identify this architecture

Expand Down Expand Up @@ -1787,6 +1809,7 @@ struct t_arch {

// Luts
std::vector<t_lut_cell> lut_cells;
std::unordered_map<std::string, std::vector<t_lut_element>> lut_elements;

//The name of the switch used for the input connection block (i.e. to
//connect routing tracks to block pins).
Expand Down
Loading