17 if (option ==
"commutative") {
19 }
else if (option ==
"non-commutative") {
21 }
else if (option ==
"untagged") {
23 }
else if (option ==
"mixed_lhs") {
25 }
else if (option ==
"mixed_any") {
27 }
else if (option ==
"all_lhs") {
30 throw std::logic_error(
"Unexpected value for operands key: " + option);
35 const auto ops_csv = options.
getStringOr(
"ops",
"add,add");
36 std::vector<OpCode> ops;
37 for (std::size_t next_pos = 0, pos = 0; next_pos != ops_csv.size(); pos = next_pos + 1) {
38 next_pos = std::min(ops_csv.find_first_of(
',', pos), ops_csv.size());
170 opgraph.
link(op_a, op_b, operands.rhs);
171 opgraph.
link(op_a2, op_b, operands.lhs);
208 const auto num_edges = options.
getIntOr(
"num_edges", 2);
209 if (num_edges == 2) {
211 opgraph.
link(op_a, op_b, operands.lhs);
212 opgraph.
link(op_a, op_b, operands.rhs);
214 for (
int i = 0; i < num_edges; ++i) {
409 const bool filter_consts = options.
getBoolOr(
"filter_consts",
false);
413 auto num_index = op.
getName().find_first_of(
"0123456789");
414 auto const_index = op.getName().find(
"const");
415 const auto num = std::stoi(op.getName().substr(num_index, std::string::npos));
416 if (filter_consts && const_index != op.getName().npos) {
418 }
else if (allowed_ids.empty() || std::find(allowed_ids.begin(), allowed_ids.end(), num) != allowed_ids.end()) {
419 return opgraph.
insert(std::move(op));
699 opgraph.
link(o1, o2, input);
703 maybeLink(shrl1, and3);
704 maybeLink(and3, mul5);
706 maybeLink(load7, shl8);
707 maybeLink(load7, or60);
708 maybeLink(shl8, or19);
709 maybeLink(shrl10, and12);
710 maybeLink(and12, mul14);
713 maybeLink(shl17, or19);
714 maybeLink(or19, or29);
716 maybeLink(shrl20, and22);
717 maybeLink(and22, mul24);
720 maybeLink(shl27, or29);
721 maybeLink(or29, or35);
722 maybeLink(and30, mul32);
724 maybeLink(load34, or35);
727 maybeLink(or35, xor47);
730 maybeLink(shl36, and38);
731 maybeLink(and38, xor46);
732 maybeLink(shrl40, and42);
733 maybeLink(and42, mul44);
734 maybeLink(mul44, xor46);
735 maybeLink(xor46, xor47);
736 maybeLink(xor46, xor64);
739 maybeLink(shl48, or52);
740 maybeLink(shrl50, or52);
741 maybeLink(or52, xor65);
742 maybeLink(shl53, or57);
743 maybeLink(shrl55, or57);
744 maybeLink(or57, xor62);
745 maybeLink(shl58, or60);
746 maybeLink(or60, xor63);
747 maybeLink(load61, xor62);
748 maybeLink(xor62, xor63);
749 maybeLink(xor63, xor64);
750 maybeLink(xor64, xor65);
751 maybeLink(xor65, output66);
752 maybeLink(xor65, and30);
756 maybeLink(shrl67, and69);
757 maybeLink(and69, mul71);
760 maybeLink(load73, or126);
761 maybeLink(shl74, or85);
762 maybeLink(shrl76, and78);
763 maybeLink(and78, mul80);
766 maybeLink(shl83, or85);
767 maybeLink(or85, or95);
769 maybeLink(shrl86, and88);
770 maybeLink(and88, mul90);
773 maybeLink(shl93, or95);
774 maybeLink(or95, or101);
775 maybeLink(and96, mul98);
777 maybeLink(load100, or101);
780 maybeLink(or101, xor113);
783 maybeLink(shl102, and104);
784 maybeLink(and104, xor112);
785 maybeLink(shrl106, and108);
786 maybeLink(and108, mul110);
787 maybeLink(mul110, xor112);
788 maybeLink(xor112, xor113);
789 maybeLink(xor112, xor131);
792 maybeLink(shl114, or118);
793 maybeLink(shrl116, or118);
794 maybeLink(or118, xor132);
795 maybeLink(shl119, or123);
796 maybeLink(shrl121, or123);
797 maybeLink(or123, xor129);
798 maybeLink(shl124, or126);
799 maybeLink(or126, xor130);
801 maybeLink(load128, xor129);
802 maybeLink(xor129, xor130);
803 maybeLink(xor130, xor131);
804 maybeLink(xor131, xor132);
807 maybeLink(xor132, and96);
810 maybeLink(shrl134, and136);
811 maybeLink(and136, mul138);
814 maybeLink(load140, or193);
815 maybeLink(shl141, or152);
816 maybeLink(shrl143, and145);
817 maybeLink(and145, mul147);
820 maybeLink(shl150, or152);
821 maybeLink(or152, or162);
823 maybeLink(shrl153, and155);
824 maybeLink(and155, mul157);
827 maybeLink(shl160, or162);
828 maybeLink(or162, or168);
829 maybeLink(and163, mul165);
831 maybeLink(load167, or168);
834 maybeLink(or168, xor180);
837 maybeLink(shl169, and171);
838 maybeLink(and171, xor179);
839 maybeLink(shrl173, and175);
840 maybeLink(and175, mul177);
841 maybeLink(mul177, xor179);
842 maybeLink(xor179, xor180);
843 maybeLink(xor179, xor198);
846 maybeLink(shl181, or185);
847 maybeLink(shrl183, or185);
848 maybeLink(or185, xor199);
849 maybeLink(shl186, or190);
850 maybeLink(shrl188, or190);
851 maybeLink(or190, xor196);
852 maybeLink(shl191, or193);
853 maybeLink(or193, xor197);
855 maybeLink(load195, xor196);
856 maybeLink(xor196, xor197);
857 maybeLink(xor197, xor198);
858 maybeLink(xor198, xor199);
862 maybeLink(xor199, and163);
864 maybeLink(shrl201, and203);
865 maybeLink(and203, mul205);
868 maybeLink(load207, or260);
869 maybeLink(shl208, or219);
870 maybeLink(shrl210, and212);
871 maybeLink(and212, mul214);
874 maybeLink(shl217, or219);
875 maybeLink(or219, or229);
877 maybeLink(shrl220, and222);
878 maybeLink(and222, mul224);
881 maybeLink(shl227, or229);
882 maybeLink(or229, or235);
883 maybeLink(and230, mul232);
885 maybeLink(load234, or235);
888 maybeLink(or235, xor247);
891 maybeLink(shl236, and238);
892 maybeLink(and238, xor246);
893 maybeLink(shrl240, and242);
894 maybeLink(and242, mul244);
895 maybeLink(mul244, xor246);
896 maybeLink(xor246, xor247);
897 maybeLink(xor246, xor265);
900 maybeLink(shl248, or252);
901 maybeLink(shrl250, or252);
902 maybeLink(or252, xor266);
903 maybeLink(shl253, or257);
904 maybeLink(shrl255, or257);
905 maybeLink(or257, xor263);
906 maybeLink(shl258, or260);
907 maybeLink(or260, xor264);
909 maybeLink(load262, xor263);
910 maybeLink(xor263, xor264);
911 maybeLink(xor264, xor265);
912 maybeLink(xor265, xor266);
917 maybeLink(xor266, and230);
918 maybeLink(add268, add268);
921 maybeLink(const4, and3);
922 maybeLink(const6, mul5);
925 maybeLink(const13, and12);
926 maybeLink(const15, mul14);
929 maybeLink(const23, and22);
930 maybeLink(const25, mul24);
932 maybeLink(const31, and30);
933 maybeLink(const33, mul32);
935 maybeLink(const39, and38);
937 maybeLink(const43, and42);
938 maybeLink(const45, mul44);
945 maybeLink(const70, and69);
946 maybeLink(const72, mul71);
949 maybeLink(const79, and78);
950 maybeLink(const81, mul80);
953 maybeLink(const89, and88);
954 maybeLink(const91, mul90);
956 maybeLink(const97, and96);
957 maybeLink(const99, mul98);
959 maybeLink(const105, and104);
961 maybeLink(const109, and108);
962 maybeLink(const111, mul110);
969 maybeLink(const137, and136);
970 maybeLink(const139, mul138);
973 maybeLink(const146, and145);
974 maybeLink(const148, mul147);
977 maybeLink(const156, and155);
978 maybeLink(const158, mul157);
980 maybeLink(const164, and163);
981 maybeLink(const166, mul165);
983 maybeLink(const172, and171);
985 maybeLink(const176, and175);
986 maybeLink(const178, mul177);
993 maybeLink(const204, and203);
994 maybeLink(const206, mul205);
997 maybeLink(const213, and212);
998 maybeLink(const215, mul214);
1001 maybeLink(const223, and222);
1002 maybeLink(const225, mul224);
1004 maybeLink(const231, and230);
1005 maybeLink(const233, mul232);
1007 maybeLink(const239, and238);
1009 maybeLink(const243, and242);
1010 maybeLink(const245, mul244);
1016 maybeLink(const269, add268);
1023 const auto num_levels = options.
getInt(
"num_levels");
1024 const auto op_fanout = options.
getIntOr(
"op_fanout", 1);
1025 const auto num_trees = options.
getIntOr(
"num_trees", 1);
1026 const auto level_xshift = options.
getIntOr(
"level_xshift", 0);
1027 const auto tree_ovelap = options.
getRealOr(
"tree_ovelap", 0);
1029 const auto opcode_arity = options.
getIntOr(
"opcode_arity", 2);
1031 if (not( num_levels > 0)) {
throw std::invalid_argument(
"num_levels must be > 0 (it is " +
std::to_string(num_levels) +
')'); }
1032 if (not( op_fanout > 0)) {
throw std::invalid_argument(
"op_fanout must be > 0 (it is " +
std::to_string(op_fanout) +
')'); }
1033 if (not( num_trees > 0)) {
throw std::invalid_argument(
"num_trees must be > 0 (it is " +
std::to_string(num_trees) +
')'); }
1034 if (not( level_xshift >= 0)) {
throw std::invalid_argument(
"level_xshift must be >= 0 (it is " +
std::to_string(level_xshift) +
')'); }
1035 if (not( tree_ovelap >= 0)) {
throw std::invalid_argument(
"tree_ovelap must be >= 0 (it is " +
std::to_string(tree_ovelap) +
')'); }
1036 if (not( tree_ovelap <= 1)) {
throw std::invalid_argument(
"tree_ovelap must be <= 1 (it is " +
std::to_string(tree_ovelap) +
')'); }
1038 const auto tree_arity = opcode_arity + 1 - op_fanout;
1040 const auto level_size = [&](
long long level) ->
long long {
1041 const long long for_one_tree = std::lround(std::pow(tree_arity, level));
1042 const long long overlapping_for_one_tree = std::lround(tree_ovelap * for_one_tree);
1043 return for_one_tree + (num_trees - 1) * (for_one_tree - overlapping_for_one_tree);
1046 std::vector<OpGraph::OpDescriptor> inputs;
1047 for (
int i = 0; i < level_size(num_levels); ++i) {
1053 std::vector<OpGraph::OpDescriptor> current_row = inputs;
1054 std::vector<OpGraph::OpDescriptor> previous_row;
1055 for (
int l = num_levels - 1; l != 0; ++l) {
1056 current_row.clear();
1058 for (
long long i = 0; i != level_size(l); ++i) {
1063 const auto& opdesc = current_row.back();
1064 for (
int a = 0; a != opcode_arity; ++a) {
1069 std::rotate(previous_row.begin(), std::next(previous_row.begin(), level_xshift), previous_row.end());
1070 std::swap(current_row, previous_row);
1073 std::vector<OpGraph::OpDescriptor> outputs;
1074 for (
int i = 0; i != num_trees; ++i) {
1075 outputs.push_back(opgraph.
insert(
1076 previous_row.at(i % previous_row.size()),
1088 using std::make_tuple;
1090 const auto w = options.
getInt(
"width");
1091 const auto h = options.
getInt(
"height");
1092 const auto Nc = options.
getInt(
"num_contexts");
1093 const auto num_consts_in_pe = options.
getIntOr(
"num_consts_in_pe", 0);
1094 const auto self_loop_via_regfile = options.
getBoolOr(
"self_loop_via_regfile",
false);
1098 const auto make_const_op = [&](
int x,
int y,
int c,
int i) {
1105 for (
int c = 0; c < Nc; ++c) {
1106 for (
int x = 0; x < w; ++x) {
1107 for (
int y = 0; y < h; ++y) {
1116 for (
int c = 0; c < Nc; ++c) {
1117 for (
int x = 0; x < w; ++x) {
1118 for (
int y = 0; y < h; ++y) {
1119 const auto& op = loc2op.at(make_tuple(c,x,y));
1121 if ((c+x+y) % 2 == 0 && self_loop_via_regfile) {
1123 }
else if (num_consts_in_pe > 1) {
1132 if ((c+x+y) % 2 == 1 && self_loop_via_regfile) {
1134 }
else if (num_consts_in_pe > 0) {