Skip to content

Commit 08a013c

Browse files
committed
moved pinloc calculation to read_xml_arch using physical tile info.
Detached the physical tile pinlocations from the pb_graph information. Now all the `custom` pinlocations pattern is built from the information present in the physical tile types only. Signed-off-by: Alessandro Comodi <[email protected]>
1 parent 84a4181 commit 08a013c

File tree

7 files changed

+311
-182
lines changed

7 files changed

+311
-182
lines changed

libs/libarchfpga/src/physical_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,8 @@ typedef const t_physical_tile_type* t_physical_tile_type_ptr;
649649
* tile_type: pointer to the associated tile type
650650
* port_class: port belongs to recognized set of ports in class library
651651
* index: port index by index in array of parent pb_type
652+
* absolute_first_pin_index: absolute index of the first pin in the physical tile.
653+
* All the other pin indices can be calculated with num_pins
652654
* port_index_by_type index of port by type (index by input, output, or clock)
653655
* equivalence: Applies to logic block I/Os and to primitive inputs only
654656
*/
@@ -661,6 +663,7 @@ struct t_physical_port {
661663
PortEquivalence equivalent = PortEquivalence::NONE;
662664

663665
int index;
666+
int absolute_first_pin_index;
664667
int port_index_by_type;
665668
int tile_type_index;
666669
};

libs/libarchfpga/src/read_xml_arch_file.cpp

Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "vtr_util.h"
5252
#include "vtr_memory.h"
5353
#include "vtr_digest.h"
54+
#include "vtr_token.h"
5455

5556
#include "arch_types.h"
5657
#include "arch_util.h"
@@ -80,6 +81,14 @@ static void SetupPinLocationsAndPinClasses(pugi::xml_node Locations,
8081
t_physical_tile_type* PhysicalTileType,
8182
const pugiutil::loc_data& loc_data);
8283

84+
static void LoadPinLoc(pugi::xml_node Locations,
85+
t_physical_tile_type* type,
86+
const pugiutil::loc_data& loc_data);
87+
static std::pair<int, int> ProcessCustomPinLoc(pugi::xml_node Locations,
88+
t_physical_tile_type_ptr type,
89+
const char* pin_loc_string,
90+
const pugiutil::loc_data& loc_data);
91+
8392
/* Process XML hierarchy */
8493
static void ProcessTiles(pugi::xml_node Node,
8594
std::vector<t_physical_tile_type>& PhysicalTileTypes,
@@ -203,6 +212,8 @@ e_side string_to_side(std::string side_str);
203212
static void link_physical_logical_types(std::vector<t_physical_tile_type>& PhysicalTileTypes,
204213
std::vector<t_logical_block_type>& LogicalBlockTypes);
205214

215+
static const t_physical_port* get_port_by_name(t_physical_tile_type_ptr type, const char* port_name);
216+
206217
/*
207218
*
208219
*
@@ -653,6 +664,283 @@ static void SetupPinLocationsAndPinClasses(pugi::xml_node Locations,
653664
VTR_ASSERT(pin_count == PhysicalTileType->num_pins);
654665
}
655666

667+
static void LoadPinLoc(pugi::xml_node Locations,
668+
t_physical_tile_type* type,
669+
const pugiutil::loc_data& loc_data) {
670+
type->pin_width_offset.resize(type->num_pins, 0);
671+
type->pin_height_offset.resize(type->num_pins, 0);
672+
673+
std::vector<int> physical_pin_counts(type->num_pins, 0);
674+
if (type->pin_location_distribution == E_SPREAD_PIN_DISTR) {
675+
/* evenly distribute pins starting at bottom left corner */
676+
677+
int num_sides = 4 * (type->width * type->height);
678+
int side_index = 0;
679+
int count = 0;
680+
for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) {
681+
for (int width = 0; width < type->width; ++width) {
682+
for (int height = 0; height < type->height; ++height) {
683+
for (int pin_offset = 0; pin_offset < (type->num_pins / num_sides) + 1; ++pin_offset) {
684+
int pin_num = side_index + pin_offset * num_sides;
685+
if (pin_num < type->num_pins) {
686+
type->pinloc[width][height][side][pin_num] = true;
687+
type->pin_width_offset[pin_num] += width;
688+
type->pin_height_offset[pin_num] += height;
689+
physical_pin_counts[pin_num] += 1;
690+
count++;
691+
}
692+
}
693+
side_index++;
694+
}
695+
}
696+
}
697+
VTR_ASSERT(side_index == num_sides);
698+
VTR_ASSERT(count == type->num_pins);
699+
} else if (type->pin_location_distribution == E_PERIMETER_PIN_DISTR) {
700+
//Add one pin at-a-time to perimeter sides in round-robin order
701+
int ipin = 0;
702+
while (ipin < type->num_pins) {
703+
for (int width = 0; width < type->width; ++width) {
704+
for (int height = 0; height < type->height; ++height) {
705+
for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) {
706+
if (((width == 0 && side == LEFT)
707+
|| (height == type->height - 1 && side == TOP)
708+
|| (width == type->width - 1 && side == RIGHT)
709+
|| (height == 0 && side == BOTTOM))
710+
&& ipin < type->num_pins) {
711+
//On a side, with pins still to allocate
712+
713+
type->pinloc[width][height][side][ipin] = true;
714+
type->pin_width_offset[ipin] += width;
715+
type->pin_height_offset[ipin] += height;
716+
physical_pin_counts[ipin] += 1;
717+
++ipin;
718+
}
719+
}
720+
}
721+
}
722+
}
723+
VTR_ASSERT(ipin == type->num_pins);
724+
725+
} else if (type->pin_location_distribution == E_SPREAD_INPUTS_PERIMETER_OUTPUTS_PIN_DISTR) {
726+
//Collect the sets of block input/output pins
727+
std::vector<int> input_pins;
728+
std::vector<int> output_pins;
729+
for (int pin_num = 0; pin_num < type->num_pins; ++pin_num) {
730+
int iclass = type->pin_class[pin_num];
731+
732+
if (type->class_inf[iclass].type == RECEIVER) {
733+
input_pins.push_back(pin_num);
734+
} else {
735+
VTR_ASSERT(type->class_inf[iclass].type == DRIVER);
736+
output_pins.push_back(pin_num);
737+
}
738+
}
739+
740+
//Allocate the inputs one pin at-a-time in a round-robin order
741+
//to all sides
742+
size_t ipin = 0;
743+
while (ipin < input_pins.size()) {
744+
for (int width = 0; width < type->width; ++width) {
745+
for (int height = 0; height < type->height; ++height) {
746+
for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) {
747+
if (ipin < input_pins.size()) {
748+
//Pins still to allocate
749+
750+
int pin_num = input_pins[ipin];
751+
752+
type->pinloc[width][height][side][pin_num] = true;
753+
type->pin_width_offset[pin_num] += width;
754+
type->pin_height_offset[pin_num] += height;
755+
physical_pin_counts[pin_num] += 1;
756+
++ipin;
757+
}
758+
}
759+
}
760+
}
761+
}
762+
VTR_ASSERT(ipin == input_pins.size());
763+
764+
//Allocate the outputs one pin at-a-time to perimeter sides in round-robin order
765+
ipin = 0;
766+
while (ipin < output_pins.size()) {
767+
for (int width = 0; width < type->width; ++width) {
768+
for (int height = 0; height < type->height; ++height) {
769+
for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) {
770+
if (((width == 0 && side == LEFT)
771+
|| (height == type->height - 1 && side == TOP)
772+
|| (width == type->width - 1 && side == RIGHT)
773+
|| (height == 0 && side == BOTTOM))
774+
&& ipin < output_pins.size()) {
775+
//On a perimeter side, with pins still to allocate
776+
777+
int pin_num = output_pins[ipin];
778+
779+
type->pinloc[width][height][side][pin_num] = true;
780+
type->pin_width_offset[pin_num] += width;
781+
type->pin_height_offset[pin_num] += height;
782+
physical_pin_counts[pin_num] += 1;
783+
++ipin;
784+
}
785+
}
786+
}
787+
}
788+
}
789+
VTR_ASSERT(ipin == output_pins.size());
790+
791+
} else {
792+
VTR_ASSERT(type->pin_location_distribution == E_CUSTOM_PIN_DISTR);
793+
int count = 0;
794+
for (int width = 0; width < type->width; ++width) {
795+
for (int height = 0; height < type->height; ++height) {
796+
for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) {
797+
for (int pin = 0; pin < type->num_pin_loc_assignments[width][height][side]; ++pin) {
798+
799+
auto pin_range = ProcessCustomPinLoc(Locations,
800+
type,
801+
type->pin_loc_assignments[width][height][side][pin],
802+
loc_data);
803+
804+
for (int pin_num = pin_range.first; pin_num < pin_range.second; ++pin_num) {
805+
VTR_ASSERT(pin_num < type->num_pins / type->capacity);
806+
for (int capacity = 0; capacity < type->capacity; ++capacity) {
807+
type->pinloc[width][height][side][pin_num + capacity * type->num_pins / type->capacity] = true;
808+
type->pin_width_offset[pin_num + capacity * type->num_pins / type->capacity] += width;
809+
type->pin_height_offset[pin_num + capacity * type->num_pins / type->capacity] += height;
810+
physical_pin_counts[pin_num + capacity * type->num_pins / type->capacity] += 1;
811+
VTR_ASSERT(count < type->num_pins);
812+
}
813+
}
814+
}
815+
}
816+
}
817+
}
818+
}
819+
820+
for (int ipin = 0; ipin < type->num_pins; ++ipin) {
821+
VTR_ASSERT(physical_pin_counts[ipin] >= 1);
822+
823+
type->pin_width_offset[ipin] /= physical_pin_counts[ipin];
824+
type->pin_height_offset[ipin] /= physical_pin_counts[ipin];
825+
826+
VTR_ASSERT(type->pin_width_offset[ipin] >= 0 && type->pin_width_offset[ipin] < type->width);
827+
VTR_ASSERT(type->pin_height_offset[ipin] >= 0 && type->pin_height_offset[ipin] < type->height);
828+
}
829+
}
830+
831+
static std::pair<int, int> ProcessCustomPinLoc(pugi::xml_node Locations,
832+
t_physical_tile_type_ptr type,
833+
const char* pin_loc_string,
834+
const pugiutil::loc_data& loc_data) {
835+
int num_tokens;
836+
auto tokens = GetTokensFromString(pin_loc_string, &num_tokens);
837+
838+
int token_index = 0;
839+
auto token = tokens[token_index];
840+
841+
if (token.type != TOKEN_STRING || 0 != strcmp(token.data, type->name)) {
842+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations),
843+
"Wrong physical type name of the port: %s\n", pin_loc_string);
844+
}
845+
846+
token_index++;
847+
token = tokens[token_index];
848+
849+
if (token.type != TOKEN_DOT) {
850+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations),
851+
"No dot is present to separate type name and port name: %s\n", pin_loc_string);
852+
}
853+
854+
token_index++;
855+
token = tokens[token_index];
856+
857+
if (token.type != TOKEN_STRING) {
858+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations),
859+
"No port name is present: %s\n", pin_loc_string);
860+
}
861+
862+
auto port = get_port_by_name(type, token.data);
863+
VTR_ASSERT(port != nullptr);
864+
int abs_first_pin_idx = port->absolute_first_pin_index;
865+
866+
std::pair<int, int> pins;
867+
868+
token_index++;
869+
870+
// All the pins of the port are taken or the port has a single pin
871+
if (token_index == num_tokens) {
872+
return std::make_pair(abs_first_pin_idx, abs_first_pin_idx + port->num_pins);
873+
}
874+
875+
token = tokens[token_index];
876+
877+
if (token.type != TOKEN_OPEN_SQUARE_BRACKET) {
878+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations),
879+
"No open square bracket present: %s\n", pin_loc_string);
880+
}
881+
882+
token_index++;
883+
token = tokens[token_index];
884+
885+
if (token.type != TOKEN_INT) {
886+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations),
887+
"No integer to indicate least significant pin index: %s\n", pin_loc_string);
888+
}
889+
890+
int first_pin = vtr::atoi(token.data);
891+
892+
token_index++;
893+
token = tokens[token_index];
894+
895+
// Single pin is specified
896+
if (token.type != TOKEN_COLON) {
897+
if (token.type != TOKEN_CLOSE_SQUARE_BRACKET) {
898+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations),
899+
"No closing bracket: %s\n", pin_loc_string);
900+
}
901+
902+
token_index++;
903+
904+
if (token_index != num_tokens) {
905+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations),
906+
"pin location should be completed, but more tokens are present: %s\n", pin_loc_string);
907+
}
908+
909+
return std::make_pair(abs_first_pin_idx + first_pin, abs_first_pin_idx + first_pin + 1);
910+
}
911+
912+
token_index++;
913+
token = tokens[token_index];
914+
915+
if (token.type != TOKEN_INT) {
916+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations),
917+
"No integer to indicate most significant pin index: %s\n", pin_loc_string);
918+
}
919+
920+
int last_pin = vtr::atoi(token.data);
921+
922+
token_index++;
923+
token = tokens[token_index];
924+
925+
if (token.type != TOKEN_CLOSE_SQUARE_BRACKET) {
926+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations),
927+
"No closed square bracket: %s\n", pin_loc_string);
928+
}
929+
930+
token_index++;
931+
932+
if (token_index != num_tokens) {
933+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations),
934+
"pin location should be completed, but more tokens are present: %s\n", pin_loc_string);
935+
}
936+
937+
if (first_pin > last_pin) {
938+
std::swap(first_pin, last_pin);
939+
}
940+
941+
return std::make_pair(abs_first_pin_idx + first_pin, abs_first_pin_idx + last_pin + 1);
942+
}
943+
656944
static void ProcessPinToPinAnnotations(pugi::xml_node Parent,
657945
t_pin_to_pin_annotation* annotation,
658946
t_pb_type* parent_pb_type,
@@ -2687,6 +2975,8 @@ static void ProcessTiles(pugi::xml_node Node,
26872975
/* Load pin names and classes and locations */
26882976
Cur = get_single_child(CurTileType, "pinlocations", loc_data, OPTIONAL);
26892977
SetupPinLocationsAndPinClasses(Cur, &PhysicalTileType, loc_data);
2978+
LoadPinLoc(Cur, &PhysicalTileType, loc_data);
2979+
26902980

26912981
//Warn that gridlocations is no longer supported
26922982
//TODO: eventually remove
@@ -2763,6 +3053,7 @@ static void ProcessTilePorts(pugi::xml_node Parent,
27633053

27643054
int iport = 0;
27653055
int k;
3056+
int absolute_first_pin_index = 0;
27663057

27673058
for (int itype = 0; itype < 3; itype++) {
27683059
if (itype == 0) {
@@ -2779,9 +3070,12 @@ static void ProcessTilePorts(pugi::xml_node Parent,
27793070
t_physical_port port;
27803071

27813072
port.index = iport;
3073+
port.absolute_first_pin_index = absolute_first_pin_index;
27823074
port.port_index_by_type = k;
27833075
ProcessTilePort(Cur, &port, loc_data);
27843076

3077+
absolute_first_pin_index += port.num_pins;
3078+
27853079
//Check port name duplicates
27863080
auto result = tile_port_names.insert(pair<std::string, int>(port.name, 0));
27873081
if (!result.second) {
@@ -4407,3 +4701,13 @@ static void link_physical_logical_types(std::vector<t_physical_tile_type>& Physi
44074701
}
44084702
}
44094703
}
4704+
4705+
static const t_physical_port* get_port_by_name(t_physical_tile_type_ptr type, const char* port_name) {
4706+
for (auto port : type->ports) {
4707+
if (0 == strcmp(port.name, port_name)) {
4708+
return &type->ports[port.index];
4709+
}
4710+
}
4711+
4712+
return nullptr;
4713+
}

vpr/src/util/token.cpp renamed to libs/libvtrutil/src/vtr_token.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ using namespace std;
1111
#include "vtr_log.h"
1212
#include "vtr_util.h"
1313
#include "vtr_memory.h"
14-
15-
#include "token.h"
16-
#include "read_xml_util.h"
14+
#include "vtr_token.h"
1715

1816
enum e_token_type GetTokenTypeFromChar(const enum e_token_type cur_token_type,
1917
const char cur);
File renamed without changes.

0 commit comments

Comments
 (0)