51
51
#include " vtr_util.h"
52
52
#include " vtr_memory.h"
53
53
#include " vtr_digest.h"
54
+ #include " vtr_token.h"
54
55
55
56
#include " arch_types.h"
56
57
#include " arch_util.h"
@@ -80,6 +81,14 @@ static void SetupPinLocationsAndPinClasses(pugi::xml_node Locations,
80
81
t_physical_tile_type* PhysicalTileType,
81
82
const pugiutil::loc_data& loc_data);
82
83
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
+
83
92
/* Process XML hierarchy */
84
93
static void ProcessTiles (pugi::xml_node Node,
85
94
std::vector<t_physical_tile_type>& PhysicalTileTypes,
@@ -203,6 +212,8 @@ e_side string_to_side(std::string side_str);
203
212
static void link_physical_logical_types (std::vector<t_physical_tile_type>& PhysicalTileTypes,
204
213
std::vector<t_logical_block_type>& LogicalBlockTypes);
205
214
215
+ static const t_physical_port* get_port_by_name (t_physical_tile_type_ptr type, const char * port_name);
216
+
206
217
/*
207
218
*
208
219
*
@@ -653,6 +664,283 @@ static void SetupPinLocationsAndPinClasses(pugi::xml_node Locations,
653
664
VTR_ASSERT (pin_count == PhysicalTileType->num_pins );
654
665
}
655
666
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
+
656
944
static void ProcessPinToPinAnnotations (pugi::xml_node Parent,
657
945
t_pin_to_pin_annotation* annotation,
658
946
t_pb_type* parent_pb_type,
@@ -2687,6 +2975,8 @@ static void ProcessTiles(pugi::xml_node Node,
2687
2975
/* Load pin names and classes and locations */
2688
2976
Cur = get_single_child (CurTileType, " pinlocations" , loc_data, OPTIONAL);
2689
2977
SetupPinLocationsAndPinClasses (Cur, &PhysicalTileType, loc_data);
2978
+ LoadPinLoc (Cur, &PhysicalTileType, loc_data);
2979
+
2690
2980
2691
2981
// Warn that gridlocations is no longer supported
2692
2982
// TODO: eventually remove
@@ -2763,6 +3053,7 @@ static void ProcessTilePorts(pugi::xml_node Parent,
2763
3053
2764
3054
int iport = 0 ;
2765
3055
int k;
3056
+ int absolute_first_pin_index = 0 ;
2766
3057
2767
3058
for (int itype = 0 ; itype < 3 ; itype++) {
2768
3059
if (itype == 0 ) {
@@ -2779,9 +3070,12 @@ static void ProcessTilePorts(pugi::xml_node Parent,
2779
3070
t_physical_port port;
2780
3071
2781
3072
port.index = iport;
3073
+ port.absolute_first_pin_index = absolute_first_pin_index;
2782
3074
port.port_index_by_type = k;
2783
3075
ProcessTilePort (Cur, &port, loc_data);
2784
3076
3077
+ absolute_first_pin_index += port.num_pins ;
3078
+
2785
3079
// Check port name duplicates
2786
3080
auto result = tile_port_names.insert (pair<std::string, int >(port.name , 0 ));
2787
3081
if (!result.second ) {
@@ -4407,3 +4701,13 @@ static void link_physical_logical_types(std::vector<t_physical_tile_type>& Physi
4407
4701
}
4408
4702
}
4409
4703
}
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
+ }
0 commit comments