diff options
author | Nathan Otterness <otternes@cs.unc.edu> | 2016-05-04 15:19:33 -0400 |
---|---|---|
committer | Nathan Otterness <otternes@cs.unc.edu> | 2016-05-04 15:19:33 -0400 |
commit | 9bfd0b21b94a8032e13c2337a67aa2b6b2c57f4b (patch) | |
tree | a99f1d56cf571213c7c7d1ce9a58b6eb11f43758 | |
parent | ecf4342e34e0b1b90229b5c452e8fe7f3483a344 (diff) |
Add more argument parsingwip_wait_free
-rw-r--r-- | include/pgm.h | 17 | ||||
-rw-r--r-- | sample_arg.txt | 26 | ||||
-rw-r--r-- | tools/pgmrt.cpp | 93 |
3 files changed, 126 insertions, 10 deletions
diff --git a/include/pgm.h b/include/pgm.h index cafb18c..dd72bf6 100644 --- a/include/pgm.h +++ b/include/pgm.h | |||
@@ -90,8 +90,17 @@ typedef struct pgm_edge_attr | |||
90 | size_t nr_consume; /* #tokens consumed per invocation */ | 90 | size_t nr_consume; /* #tokens consumed per invocation */ |
91 | size_t nr_threshold; /* #tokens required before consume allowed */ | 91 | size_t nr_threshold; /* #tokens required before consume allowed */ |
92 | 92 | ||
93 | // This will be 1 for producer-consumer buffer, 2 for wait-free buffer and | ||
94 | // 0 for an unknown type. | ||
95 | int ipc_type_to_use; | ||
96 | |||
93 | pgm_edge_type_t type; /* type indicating underlying IPC of the edge */ | 97 | pgm_edge_type_t type; /* type indicating underlying IPC of the edge */ |
94 | 98 | ||
99 | /* for logical page support. Refer RTSS16 paper */ | ||
100 | unsigned int color; | ||
101 | unsigned int bank; | ||
102 | unsigned long offset; | ||
103 | |||
95 | /* edge-type specific params */ | 104 | /* edge-type specific params */ |
96 | union | 105 | union |
97 | { | 106 | { |
@@ -112,10 +121,6 @@ typedef struct pgm_edge_attr | |||
112 | { | 121 | { |
113 | /* The maximum number of bytes in a wait-free buffer. */ | 122 | /* The maximum number of bytes in a wait-free buffer. */ |
114 | size_t buffer_bytes; | 123 | size_t buffer_bytes; |
115 | /* for logical page support. Refer RTSS16 paper */ | ||
116 | unsigned int color; | ||
117 | unsigned int bank; | ||
118 | unsigned long offset; | ||
119 | }; | 124 | }; |
120 | struct /* POSIX message queue params */ | 125 | struct /* POSIX message queue params */ |
121 | { | 126 | { |
@@ -139,7 +144,11 @@ static const edge_attr_t default_edge = { | |||
139 | .nr_produce = 1, | 144 | .nr_produce = 1, |
140 | .nr_consume = 1, | 145 | .nr_consume = 1, |
141 | .nr_threshold = 1, | 146 | .nr_threshold = 1, |
147 | .ipc_type_to_use = 0, | ||
142 | .type = pgm_cv_edge, | 148 | .type = pgm_cv_edge, |
149 | .color = 0, | ||
150 | .bank = 0, | ||
151 | .offset = 0, | ||
143 | }; | 152 | }; |
144 | 153 | ||
145 | /* | 154 | /* |
diff --git a/sample_arg.txt b/sample_arg.txt index 7e118fe..507170b 100644 --- a/sample_arg.txt +++ b/sample_arg.txt | |||
@@ -1 +1,25 @@ | |||
1 | ./pgmrt --wait --cluster node0:0,node1:3,node2:-1,node4:-1 --graph node0:node1,node0:node2,node1:node4 --rates node0:1:100 --execution node0:10,node1:15,node2:20,node4:10 --budget node0:99,node1:99,node2:99,node4:99 --criticality node0:0,node1:1,node2:2,node4:2 --buffer node0:node1:512,node0:node2:256,node1:node4:32 --wsCycle 3 --etoe 100 --duration 3 & | 1 | # The original invocation |
2 | |||
3 | ./pgmrt --wait --cluster node0:0,node1:3,node2:-1,node4:-1 \ | ||
4 | --graph node0:node1,node0:node2,node1:node4 \ | ||
5 | --rates node0:1:100 \ | ||
6 | --execution node0:10,node1:15,node2:20,node4:10 \ | ||
7 | --budget node0:99,node1:99,node2:99,node4:99 \ | ||
8 | --criticality node0:0,node1:1,node2:2,node4:2 \ | ||
9 | --buffer node0:node1:512,node0:node2:256,node1:node4:32 \ | ||
10 | --wsCycle 3 \ | ||
11 | --etoe 100 \ | ||
12 | --duration 3 & | ||
13 | |||
14 | # Indicates node0:node1 edge should use a wait free buffer and node0:node2 to use a producer-consumer buffer. | ||
15 | |||
16 | ./pgmrt --wait --cluster node0:0,node1:3,node2:-1,node4:-1 \ | ||
17 | --graph node0:node1,node0:node2,node1:node4@node0:node1,wf,0000ffff,000000fc,00000000@node0:node2,pc,0000ffff,000000fc,00000400 \ | ||
18 | --rates node0:1:100 \ | ||
19 | --execution node0:10,node1:15,node2:20,node4:10 \ | ||
20 | --budget node0:99,node1:99,node2:99,node4:99 \ | ||
21 | --criticality node0:0,node1:1,node2:2,node4:2 \ | ||
22 | --buffer node0:node1:512,node0:node2:256,node1:node4:32 \ | ||
23 | --wsCycle 3 \ | ||
24 | --etoe 100 \ | ||
25 | --duration 3 & | ||
diff --git a/tools/pgmrt.cpp b/tools/pgmrt.cpp index 25ad7d5..8ec9bee 100644 --- a/tools/pgmrt.cpp +++ b/tools/pgmrt.cpp | |||
@@ -4,6 +4,7 @@ | |||
4 | /* A program for running a complex PGM application. */ | 4 | /* A program for running a complex PGM application. */ |
5 | 5 | ||
6 | #include <iostream> | 6 | #include <iostream> |
7 | #include <sstream> | ||
7 | #include <thread> | 8 | #include <thread> |
8 | #include <exception> | 9 | #include <exception> |
9 | #include <stdexcept> | 10 | #include <stdexcept> |
@@ -13,6 +14,8 @@ | |||
13 | #include <cstdint> | 14 | #include <cstdint> |
14 | 15 | ||
15 | #include <errno.h> | 16 | #include <errno.h> |
17 | #include <stdio.h> | ||
18 | #include <stdlib.h> | ||
16 | #include <string.h> | 19 | #include <string.h> |
17 | 20 | ||
18 | // TODO: Use std::chrono routines instead. | 21 | // TODO: Use std::chrono routines instead. |
@@ -567,8 +570,58 @@ std::string make_edge_name(const std::string& a, const std::string& b) | |||
567 | return name; | 570 | return name; |
568 | } | 571 | } |
569 | 572 | ||
573 | typedef struct { | ||
574 | std::string EdgeName; | ||
575 | // This is 0 if unknown, 1 if wait free, or 2 if producer consumer | ||
576 | uint8_t ProducerConsumerOrWaitFree; | ||
577 | uint32_t Color; | ||
578 | uint32_t Bank; | ||
579 | uint32_t Offset; | ||
580 | } GraphEdgeAttributes; | ||
581 | |||
582 | uint32_t HexToUint32(std::string hex) { | ||
583 | std::stringstream ss; | ||
584 | uint32_t toReturn; | ||
585 | ss << std::hex << hex; | ||
586 | ss >> toReturn; | ||
587 | return toReturn; | ||
588 | } | ||
589 | |||
590 | // Graph node attribute format: | ||
591 | // ./pgmrt <...> --graph node0:node1,node0:node2@node0:node1,wf,0000ffff,000000fc,00000000@node1:... | ||
592 | // | ||
593 | // Basically, append an '@' to the end of the --graph argument string, followed | ||
594 | // by a list of <edge name>:type,color,bank,offset. Attributes for more edges | ||
595 | // can be appended using additional '@' symbols. Color, bank and offset are all | ||
596 | // in hex. | ||
597 | std::vector<GraphEdgeAttributes> ParseGraphEdgeAttributes(std::vector<std::string> desc) { | ||
598 | std::vector<std::string> attrs; | ||
599 | std::vector<GraphEdgeAttributes> toReturn; | ||
600 | for (int i = 0; i < desc.size(); i++) { | ||
601 | boost::split(attrs, desc[i], boost::is_any_of(",")); | ||
602 | if (attrs.size() != 5) { | ||
603 | printf("Error: Edge attributes must be of the format %s\n", | ||
604 | "<edge name>,<edge type (wf or pc)>,<color>,<bank>,<offset>"); | ||
605 | exit(1); | ||
606 | } | ||
607 | GraphEdgeAttributes thisEdge; | ||
608 | thisEdge.EdgeName = attrs[0]; | ||
609 | thisEdge.ProducerConsumerOrWaitFree = 0; | ||
610 | if (attrs[1] == "wf") { | ||
611 | thisEdge.ProducerConsumerOrWaitFree = 1; | ||
612 | } else if (attrs[1] == "pc") { | ||
613 | thisEdge.ProducerConsumerOrWaitFree = 2; | ||
614 | } | ||
615 | thisEdge.Color = HexToUint32(attrs[2]); | ||
616 | thisEdge.Bank = HexToUint32(attrs[3]); | ||
617 | thisEdge.Offset = HexToUint32(attrs[4]); | ||
618 | toReturn.push_back(thisEdge); | ||
619 | } | ||
620 | return toReturn; | ||
621 | } | ||
622 | |||
570 | void parse_graph_description( | 623 | void parse_graph_description( |
571 | const std::string& desc, | 624 | const std::string& desc_original, |
572 | const graph_t& g, | 625 | const graph_t& g, |
573 | std::vector<node_t>& nodes, | 626 | std::vector<node_t>& nodes, |
574 | std::vector<edge_t>& edges) | 627 | std::vector<edge_t>& edges) |
@@ -577,10 +630,14 @@ void parse_graph_description( | |||
577 | // the edges. | 630 | // the edges. |
578 | // function does not need to be fast! | 631 | // function does not need to be fast! |
579 | 632 | ||
633 | std::vector<std::string> nodeNameChunksAndAttributes; | ||
580 | // strip token information | 634 | // strip token information |
581 | std::vector<std::string> nodeNameChunks; | 635 | std::vector<std::string> nodeNameChunks; |
582 | std::set<std::string> nodeNames; // set to ensure uniqueness | 636 | std::set<std::string> nodeNames; // set to ensure uniqueness |
637 | boost::split(nodeNameChunksAndAttributes, desc_original, boost::is_any_of("@")); | ||
638 | std::string desc = nodeNameChunksAndAttributes[0]; | ||
583 | boost::split(nodeNameChunks, desc, boost::is_any_of(",") || boost::is_any_of(":")); | 639 | boost::split(nodeNameChunks, desc, boost::is_any_of(",") || boost::is_any_of(":")); |
640 | |||
584 | for(auto nStr(nodeNameChunks.begin()); nStr != nodeNameChunks.end(); ++nStr) { | 641 | for(auto nStr(nodeNameChunks.begin()); nStr != nodeNameChunks.end(); ++nStr) { |
585 | std::vector<std::string> tokenDesc; | 642 | std::vector<std::string> tokenDesc; |
586 | boost::split(tokenDesc, *nStr, boost::is_any_of(".")); | 643 | boost::split(tokenDesc, *nStr, boost::is_any_of(".")); |
@@ -591,7 +648,17 @@ void parse_graph_description( | |||
591 | for(auto nStr(nodeNames.begin()); nStr != nodeNames.end(); ++nStr) { | 648 | for(auto nStr(nodeNames.begin()); nStr != nodeNames.end(); ++nStr) { |
592 | printf("Node = %s\n", nStr->c_str()); | 649 | printf("Node = %s\n", nStr->c_str()); |
593 | } | 650 | } |
594 | 651 | ||
652 | // Delete the original edge definitions in the attributes list... | ||
653 | nodeNameChunksAndAttributes[0] = nodeNameChunksAndAttributes[nodeNameChunksAndAttributes.size() - 1]; | ||
654 | nodeNameChunksAndAttributes.pop_back(); | ||
655 | std::vector<GraphEdgeAttributes> edgeAttrs = ParseGraphEdgeAttributes(nodeNameChunksAndAttributes); | ||
656 | for (int i = 0; i < edgeAttrs.size(); i++) { | ||
657 | printf("Edge %s: Type %d, color 0x%08x, bank 0x%08x, offset 0x%08x\n", | ||
658 | edgeAttrs[i].EdgeName.c_str(), (int) edgeAttrs[i].ProducerConsumerOrWaitFree, | ||
659 | edgeAttrs[i].Color, edgeAttrs[i].Bank, edgeAttrs[i].Offset); | ||
660 | } | ||
661 | |||
595 | // process each uniquely named node | 662 | // process each uniquely named node |
596 | std::map<std::string, node_t> nodeMap; | 663 | std::map<std::string, node_t> nodeMap; |
597 | for(auto nStr(nodeNames.begin()); nStr != nodeNames.end(); ++nStr) { | 664 | for(auto nStr(nodeNames.begin()); nStr != nodeNames.end(); ++nStr) { |
@@ -604,7 +671,9 @@ void parse_graph_description( | |||
604 | // create all the edges. | 671 | // create all the edges. |
605 | std::vector<std::string> edgeDesc; | 672 | std::vector<std::string> edgeDesc; |
606 | boost::split(edgeDesc, desc, boost::is_any_of(",")); | 673 | boost::split(edgeDesc, desc, boost::is_any_of(",")); |
674 | GraphEdgeAttributes *thisEdgeAttributes; | ||
607 | for(auto eStr(edgeDesc.begin()); eStr != edgeDesc.end(); ++eStr) { | 675 | for(auto eStr(edgeDesc.begin()); eStr != edgeDesc.end(); ++eStr) { |
676 | thisEdgeAttributes = NULL; | ||
608 | std::vector<std::string> nodePair; | 677 | std::vector<std::string> nodePair; |
609 | boost::split(nodePair, *eStr, boost::is_any_of(":")); | 678 | boost::split(nodePair, *eStr, boost::is_any_of(":")); |
610 | if(nodePair.size() > 2) { | 679 | if(nodePair.size() > 2) { |
@@ -614,7 +683,7 @@ void parse_graph_description( | |||
614 | // assume single-node graph | 683 | // assume single-node graph |
615 | continue; | 684 | continue; |
616 | } | 685 | } |
617 | 686 | std::string edgeName = ""; | |
618 | int nr_produce = 1; | 687 | int nr_produce = 1; |
619 | int nr_consume = 1; | 688 | int nr_consume = 1; |
620 | int nr_threshold = 1; | 689 | int nr_threshold = 1; |
@@ -627,6 +696,7 @@ void parse_graph_description( | |||
627 | nr_produce = boost::lexical_cast<int>(tokenDesc[1]); | 696 | nr_produce = boost::lexical_cast<int>(tokenDesc[1]); |
628 | nodePair[0] = tokenDesc[0]; | 697 | nodePair[0] = tokenDesc[0]; |
629 | } | 698 | } |
699 | edgeName = tokenDesc[0] + ":"; | ||
630 | tokenDesc.clear(); | 700 | tokenDesc.clear(); |
631 | boost::split(tokenDesc, nodePair[1], boost::is_any_of(".")); | 701 | boost::split(tokenDesc, nodePair[1], boost::is_any_of(".")); |
632 | if(tokenDesc.size() > 1) { | 702 | if(tokenDesc.size() > 1) { |
@@ -639,8 +709,14 @@ void parse_graph_description( | |||
639 | } | 709 | } |
640 | nodePair[1] = tokenDesc[0]; | 710 | nodePair[1] = tokenDesc[0]; |
641 | } | 711 | } |
642 | 712 | edgeName += tokenDesc[0]; | |
643 | 713 | thisEdgeAttributes = NULL; | |
714 | for (int j = 0; j < edgeAttrs.size(); j++) { | ||
715 | if (edgeAttrs[j].EdgeName == edgeName) { | ||
716 | thisEdgeAttributes = &(edgeAttrs[j]); | ||
717 | break; | ||
718 | } | ||
719 | } | ||
644 | edge_t e; | 720 | edge_t e; |
645 | edge_attr_t cv_attr; | 721 | edge_attr_t cv_attr; |
646 | memset(&cv_attr, 0, sizeof(cv_attr)); | 722 | memset(&cv_attr, 0, sizeof(cv_attr)); |
@@ -648,6 +724,13 @@ void parse_graph_description( | |||
648 | cv_attr.nr_produce = nr_produce; | 724 | cv_attr.nr_produce = nr_produce; |
649 | cv_attr.nr_consume = nr_consume; | 725 | cv_attr.nr_consume = nr_consume; |
650 | cv_attr.nr_threshold = nr_threshold; | 726 | cv_attr.nr_threshold = nr_threshold; |
727 | if (thisEdgeAttributes) { | ||
728 | printf("Applying additional attributes for edge %s\n", edgeName.c_str()); | ||
729 | cv_attr.color = thisEdgeAttributes->Color; | ||
730 | cv_attr.bank = thisEdgeAttributes->Bank; | ||
731 | cv_attr.offset = thisEdgeAttributes->Offset; | ||
732 | cv_attr.ipc_type_to_use = thisEdgeAttributes->ProducerConsumerOrWaitFree; | ||
733 | } | ||
651 | CheckError(pgm_init_edge(&e, nodeMap[nodePair[0]], nodeMap[nodePair[1]], | 734 | CheckError(pgm_init_edge(&e, nodeMap[nodePair[0]], nodeMap[nodePair[1]], |
652 | make_edge_name(nodePair[0], nodePair[1]).c_str(), &cv_attr)); | 735 | make_edge_name(nodePair[0], nodePair[1]).c_str(), &cv_attr)); |
653 | edges.push_back(e); | 736 | edges.push_back(e); |