Added support for placeholder tags in fasm features.
Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
diff --git a/utils/fasm/src/fasm.cpp b/utils/fasm/src/fasm.cpp
index d6d1acc..d5a3552 100644
--- a/utils/fasm/src/fasm.cpp
+++ b/utils/fasm/src/fasm.cpp
@@ -58,6 +58,28 @@
current_blk_has_prefix_ = true;
clb_prefix_map_.clear();
+
+ // Get placeholder list (if provided)
+ tags_.clear();
+ if(grid_loc.meta != nullptr && grid_loc.meta->has("fasm_placeholders")) {
+ auto* value = grid_loc.meta->get("fasm_placeholders");
+ VTR_ASSERT(value != nullptr);
+
+ // Parse placeholder definition
+ std::vector<std::string> tag_defs = vtr::split(value->front().as_string(), "\n");
+ for (auto& tag_def: tag_defs) {
+ auto parts = split_fasm_entry(tag_def, "=:", "\t ");
+ if (parts.size() == 0) {
+ continue;
+ }
+
+ VTR_ASSERT(parts.size() == 2);
+
+ VTR_ASSERT(tags_.count(parts.at(0)) == 0);
+ tags_[parts.at(0)] = parts.at(1);
+ }
+ }
+
std::string grid_prefix;
if(grid_loc.meta != nullptr && grid_loc.meta->has("fasm_prefix")) {
auto* value = grid_loc.meta->get("fasm_prefix");
@@ -719,10 +741,14 @@
std::string feature;
os >> feature;
if(os) {
+ std::string out_feature;
if(have_clb_prefix) {
- os_ << blk_prefix_ << clb_prefix;
+ out_feature += blk_prefix_;
+ out_feature += clb_prefix;
}
- os_ << feature << std::endl;
+ out_feature += feature;
+ // Substitute tags
+ os_ << substitute_tags(out_feature, tags_) << std::endl;
}
}
diff --git a/utils/fasm/src/fasm.h b/utils/fasm/src/fasm.h
index 471a8c2..1326c4c 100644
--- a/utils/fasm/src/fasm.h
+++ b/utils/fasm/src/fasm.h
@@ -94,6 +94,8 @@
std::vector<t_pb_graph_pin**> pb_graph_pin_lookup_from_index_by_type_;
std::map<const t_pb_type*, std::vector<std::pair<std::string, LutOutputDefinition>>> lut_definitions_;
std::map<const t_pb_type*, Parameters> parameters_;
+
+ std::map<const std::string, std::string> tags_;
};
} // namespace fasm
diff --git a/utils/fasm/src/fasm_utils.cpp b/utils/fasm/src/fasm_utils.cpp
index fddb62a..bc397d0 100644
--- a/utils/fasm/src/fasm_utils.cpp
+++ b/utils/fasm/src/fasm_utils.cpp
@@ -1,6 +1,8 @@
#include "fasm_utils.h"
#include "vpr_utils.h"
+#include <regex>
+
namespace fasm {
void parse_name_with_optional_index(const std::string in, std::string *name, int *index) {
@@ -30,4 +32,57 @@
return vtr::split(entry, delims);
}
+std::vector<std::string> find_tags_in_feature (const std::string& a_String) {
+ const std::regex regex ("(\\{[a-zA-Z0-9]+\\})");
+
+ std::vector<std::string> tags;
+ std::string str(a_String);
+ std::smatch match;
+
+ // Search for tags
+ while (std::regex_search(str, match, regex)) {
+ std::string tag(match.str());
+
+ // Strip braces
+ tags.push_back(tag.substr(1, tag.length()-2));
+ str = match.suffix().str();
+ }
+
+ return tags;
+}
+
+std::string substitute_tags (const std::string& a_Feature, const std::map<const std::string, std::string>& a_Tags) {
+
+ // First list tags that are given in the feature string
+ auto tags = find_tags_in_feature(a_Feature);
+ if (tags.empty()) {
+ return a_Feature;
+ }
+
+ // Check if those tags are defined, If not then throw an error
+ bool have_errors = false;
+ for (auto tag: tags) {
+ if (a_Tags.count(tag) == 0) {
+ vtr::printf_error(__FILE__, __LINE__, "fasm placeholder '%s' not defined!", tag.c_str());
+ have_errors = true;
+ }
+ }
+
+ if (have_errors) {
+ vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
+ "fasm feature '%s' contains placeholders that are not defined for the tile that it is used in!",
+ a_Feature.c_str()
+ );
+ }
+
+ // Substitute tags
+ std::string feature(a_Feature);
+ for (auto tag: tags) {
+ std::regex regex("\\{" + tag + "\\}");
+ feature = std::regex_replace(feature, regex, a_Tags.at(tag));
+ }
+
+ return feature;
+}
+
} // namespace fasm
diff --git a/utils/fasm/src/fasm_utils.h b/utils/fasm/src/fasm_utils.h
index 99f82c7..983ed9e 100644
--- a/utils/fasm/src/fasm_utils.h
+++ b/utils/fasm/src/fasm_utils.h
@@ -3,6 +3,7 @@
#include <string>
#include <vector>
+#include <map>
namespace fasm {
@@ -22,6 +23,15 @@
std::string delims,
std::string ignore);
+// Substitutes tags found in a string with their values provided by the map.
+// Thorws an error if a tag is found in the string and its value is not present
+// in the map.
+//
+// a_Feature - Fasm feature string (or any other string)
+// a_Tags - Map with tags and their values
+std::string substitute_tags (const std::string& a_Feature,
+ const std::map<const std::string, std::string>& a_Tags);
+
} // namespace fasm
#endif /* UTILS_FASM_FASM_UTILS_H_ */
diff --git a/utils/fasm/test/test_fasm.cpp b/utils/fasm/test/test_fasm.cpp
index 9be59ef..6ec278d 100644
--- a/utils/fasm/test/test_fasm.cpp
+++ b/utils/fasm/test/test_fasm.cpp
@@ -7,6 +7,7 @@
#include "arch_util.h"
#include "rr_graph_writer.h"
#include <sstream>
+#include <fstream>
static constexpr const char kArchFile[] = "test_fasm_arch.xml";
static constexpr const char kRrGraphFile[] = "test_fasm_rrgraph.xml";
@@ -78,6 +79,16 @@
fasm_string.seekg(0);
+ std::ofstream fasm_file("output.fasm", std::ios_base::out);
+ while(fasm_string) {
+ std::string line;
+ std::getline(fasm_string, line);
+ fasm_file << line << std::endl;
+ }
+
+ fasm_string.clear();
+ fasm_string.seekg(0);
+
std::set<std::tuple<int, int, short>> routing_edges;
bool found_lut5 = false;
bool found_lut6 = false;
@@ -99,13 +110,13 @@
continue;
}
- if(!found_mux1 && line == "CLB.FLE9.OUT_MUX.LUT") {
+ if(!found_mux1 && line.find(".OUT_MUX.LUT") != std::string::npos) {
found_mux1 = true;
}
- if(!found_mux2 && line == "CLB.FLE9.DISABLE_FF") {
+ if(!found_mux2 && line.find(".DISABLE_FF") != std::string::npos) {
found_mux2 = true;
}
- if(!found_mux3 && line == "CLB.FLE9.IN0") {
+ if(!found_mux3 && line.find(".IN0") != std::string::npos) {
found_mux3 = true;
}
diff --git a/utils/fasm/test/test_fasm_arch.xml b/utils/fasm/test/test_fasm_arch.xml
index dd5ac4b..6f6cf2a 100644
--- a/utils/fasm/test/test_fasm_arch.xml
+++ b/utils/fasm/test/test_fasm_arch.xml
@@ -28,20 +28,100 @@
</tile>
</tiles>
<layout>
- <fixed_layout height="10" width="10" name="test">
+ <fixed_layout height="6" width="6" name="test">
<perimeter type="io" priority="100">
<metadata>
<meta name="type">io</meta>
</metadata>
</perimeter>
<corners type="EMPTY" priority="101"/>
- <fill type="clb" priority="10">
- <metadata>
- <meta name="fasm_prefix">CLB</meta>
- </metadata>
- </fill>
- <col type="EMPTY" startx="6" repeatx="8" starty="1" priority="19"/>
- <col type="EMPTY" startx="2" repeatx="8" starty="1" priority="19"/>
+
+ <single type="clb" priority="10" x="1" y="1">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X1Y1
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+ <single type="clb" priority="10" x="1" y="2">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X1Y2
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+ <single type="clb" priority="10" x="1" y="3">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X1Y3
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+ <single type="clb" priority="10" x="1" y="4">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X1Y4
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+
+ <single type="clb" priority="10" x="2" y="1">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X2Y1
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+ <single type="clb" priority="10" x="2" y="2">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X2Y2
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+ <single type="clb" priority="10" x="2" y="3">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X2Y3
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+ <single type="clb" priority="10" x="2" y="4">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X2Y4
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+
+ <single type="clb" priority="10" x="3" y="1">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X3Y1
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+ <single type="clb" priority="10" x="3" y="2">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X3Y2
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+ <single type="clb" priority="10" x="3" y="3">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X3Y3
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+ <single type="clb" priority="10" x="3" y="4">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X3Y4
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+
+ <single type="clb" priority="10" x="4" y="1">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X4Y1
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+ <single type="clb" priority="10" x="4" y="2">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X4Y2
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+ <single type="clb" priority="10" x="4" y="3">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X4Y3
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+ <single type="clb" priority="10" x="4" y="4">
+ <metadata> <meta name="fasm_placeholders">
+ LOC=X4Y4
+ </meta> <meta name="fasm_prefix">CLB</meta> </metadata>
+ </single>
+
+<!-- <col type="EMPTY" startx="6" repeatx="8" starty="1" priority="19"/>
+ <col type="EMPTY" startx="2" repeatx="8" starty="1" priority="19"/> -->
</fixed_layout>
</layout>
<device>
@@ -267,7 +347,7 @@
</mode>
<metadata>
<meta name="fasm_prefix">
- FLE0 FLE1 FLE2 FLE3 FLE4 FLE5 FLE6 FLE7 FLE8 FLE9
+ FLE0_{LOC} FLE1_{LOC} FLE2_{LOC} FLE3_{LOC} FLE4_{LOC} FLE5_{LOC} FLE6_{LOC} FLE7_{LOC} FLE8_{LOC} FLE9_{LOC}
</meta>
</metadata>
</pb_type>