aboutsummaryrefslogtreecommitdiffstats
path: root/passes/memory/memory_bram.cc
diff options
context:
space:
mode:
Diffstat (limited to 'passes/memory/memory_bram.cc')
-rw-r--r--passes/memory/memory_bram.cc112
1 files changed, 70 insertions, 42 deletions
diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc
index 24478f2ee..0898ec288 100644
--- a/passes/memory/memory_bram.cc
+++ b/passes/memory/memory_bram.cc
@@ -105,11 +105,11 @@ struct rules_t
log_error("Bram %s variants %d and %d have different values for 'groups'.\n", log_id(name), variant, other.variant);
if (abits != other.abits)
- variant_params["\\CFG_ABITS"] = abits;
+ variant_params[ID::CFG_ABITS] = abits;
if (dbits != other.dbits)
- variant_params["\\CFG_DBITS"] = dbits;
+ variant_params[ID::CFG_DBITS] = dbits;
if (init != other.init)
- variant_params["\\CFG_INIT"] = init;
+ variant_params[ID::CFG_INIT] = init;
for (int i = 0; i < groups; i++)
{
@@ -137,9 +137,26 @@ struct rules_t
vector<vector<std::tuple<bool,IdString,Const>>> attributes;
};
+ bool attr_icase;
dict<IdString, vector<bram_t>> brams;
vector<match_t> matches;
+ std::string map_case(std::string value) const
+ {
+ if (attr_icase) {
+ for (char &c : value)
+ c = tolower(c);
+ }
+ return value;
+ }
+
+ RTLIL::Const map_case(RTLIL::Const value) const
+ {
+ if (value.flags & RTLIL::CONST_FLAG_STRING)
+ return map_case(value.decode_string());
+ return value;
+ }
+
std::ifstream infile;
vector<string> tokens;
vector<string> labels;
@@ -337,7 +354,7 @@ struct rules_t
IdString key = RTLIL::escape_id(tokens[idx].substr(c1, c2));
Const val = c2 != std::string::npos ? tokens[idx].substr(c2+1) : RTLIL::Const(1);
- data.attributes.back().emplace_back(exists, key, val);
+ data.attributes.back().emplace_back(exists, key, map_case(val));
}
continue;
}
@@ -351,6 +368,7 @@ struct rules_t
rewrite_filename(filename);
infile.open(filename);
linecount = 0;
+ attr_icase = false;
if (infile.fail())
log_error("Can't open rules file `%s'.\n", filename.c_str());
@@ -360,6 +378,11 @@ struct rules_t
if (!labels.empty())
syntax_error();
+ if (GetSize(tokens) == 2 && tokens[0] == "attr_icase") {
+ attr_icase = atoi(tokens[1].c_str());
+ continue;
+ }
+
if (tokens[0] == "bram") {
parse_bram();
continue;
@@ -414,44 +437,44 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
log(" Mapping to bram type %s (variant %d):\n", log_id(bram.name), bram.variant);
// bram.dump_config();
- int mem_size = cell->getParam("\\SIZE").as_int();
- int mem_abits = cell->getParam("\\ABITS").as_int();
- int mem_width = cell->getParam("\\WIDTH").as_int();
- // int mem_offset = cell->getParam("\\OFFSET").as_int();
+ int mem_size = cell->getParam(ID::SIZE).as_int();
+ int mem_abits = cell->getParam(ID::ABITS).as_int();
+ int mem_width = cell->getParam(ID::WIDTH).as_int();
+ // int mem_offset = cell->getParam(ID::OFFSET).as_int();
- bool cell_init = !SigSpec(cell->getParam("\\INIT")).is_fully_undef();
+ bool cell_init = !SigSpec(cell->getParam(ID::INIT)).is_fully_undef();
vector<Const> initdata;
if (cell_init) {
- Const initparam = cell->getParam("\\INIT");
+ Const initparam = cell->getParam(ID::INIT);
initdata.reserve(mem_size);
for (int i=0; i < mem_size; i++)
initdata.push_back(initparam.extract(mem_width*i, mem_width, State::Sx));
}
- int wr_ports = cell->getParam("\\WR_PORTS").as_int();
- auto wr_clken = SigSpec(cell->getParam("\\WR_CLK_ENABLE"));
- auto wr_clkpol = SigSpec(cell->getParam("\\WR_CLK_POLARITY"));
+ int wr_ports = cell->getParam(ID::WR_PORTS).as_int();
+ auto wr_clken = SigSpec(cell->getParam(ID::WR_CLK_ENABLE));
+ auto wr_clkpol = SigSpec(cell->getParam(ID::WR_CLK_POLARITY));
wr_clken.extend_u0(wr_ports);
wr_clkpol.extend_u0(wr_ports);
- SigSpec wr_en = cell->getPort("\\WR_EN");
- SigSpec wr_clk = cell->getPort("\\WR_CLK");
- SigSpec wr_data = cell->getPort("\\WR_DATA");
- SigSpec wr_addr = cell->getPort("\\WR_ADDR");
+ SigSpec wr_en = cell->getPort(ID::WR_EN);
+ SigSpec wr_clk = cell->getPort(ID::WR_CLK);
+ SigSpec wr_data = cell->getPort(ID::WR_DATA);
+ SigSpec wr_addr = cell->getPort(ID::WR_ADDR);
- int rd_ports = cell->getParam("\\RD_PORTS").as_int();
- auto rd_clken = SigSpec(cell->getParam("\\RD_CLK_ENABLE"));
- auto rd_clkpol = SigSpec(cell->getParam("\\RD_CLK_POLARITY"));
- auto rd_transp = SigSpec(cell->getParam("\\RD_TRANSPARENT"));
+ int rd_ports = cell->getParam(ID::RD_PORTS).as_int();
+ auto rd_clken = SigSpec(cell->getParam(ID::RD_CLK_ENABLE));
+ auto rd_clkpol = SigSpec(cell->getParam(ID::RD_CLK_POLARITY));
+ auto rd_transp = SigSpec(cell->getParam(ID::RD_TRANSPARENT));
rd_clken.extend_u0(rd_ports);
rd_clkpol.extend_u0(rd_ports);
rd_transp.extend_u0(rd_ports);
- SigSpec rd_en = cell->getPort("\\RD_EN");
- SigSpec rd_clk = cell->getPort("\\RD_CLK");
- SigSpec rd_data = cell->getPort("\\RD_DATA");
- SigSpec rd_addr = cell->getPort("\\RD_ADDR");
+ SigSpec rd_en = cell->getPort(ID::RD_EN);
+ SigSpec rd_clk = cell->getPort(ID::RD_CLK);
+ SigSpec rd_data = cell->getPort(ID::RD_DATA);
+ SigSpec rd_addr = cell->getPort(ID::RD_ADDR);
if (match.shuffle_enable && bram.dbits >= portinfos.at(match.shuffle_enable - 'A').enable*2 && portinfos.at(match.shuffle_enable - 'A').enable > 0 && wr_ports > 0)
{
@@ -843,7 +866,7 @@ grow_read_ports:;
}
else if (!exists)
continue;
- if (it->second != value)
+ if (rules.map_case(it->second) != value)
continue;
found = true;
break;
@@ -855,7 +878,7 @@ grow_read_ports:;
ss << "!";
IdString key = std::get<1>(sums.front());
ss << log_id(key);
- const Const &value = std::get<2>(sums.front());
+ const Const &value = rules.map_case(std::get<2>(sums.front()));
if (exists && value != Const(1))
ss << "=\"" << value.decode_string() << "\"";
@@ -915,7 +938,7 @@ grow_read_ports:;
else
initparam[i*bram.dbits+j] = padding;
}
- c->setParam("\\INIT", initparam);
+ c->setParam(ID::INIT, initparam);
}
for (auto &pi : portinfos)
@@ -1048,14 +1071,14 @@ void handle_cell(Cell *cell, const rules_t &rules)
{
log("Processing %s.%s:\n", log_id(cell->module), log_id(cell));
- bool cell_init = !SigSpec(cell->getParam("\\INIT")).is_fully_undef();
+ bool cell_init = !SigSpec(cell->getParam(ID::INIT)).is_fully_undef();
dict<string, int> match_properties;
- match_properties["words"] = cell->getParam("\\SIZE").as_int();
- match_properties["abits"] = cell->getParam("\\ABITS").as_int();
- match_properties["dbits"] = cell->getParam("\\WIDTH").as_int();
- match_properties["wports"] = cell->getParam("\\WR_PORTS").as_int();
- match_properties["rports"] = cell->getParam("\\RD_PORTS").as_int();
+ match_properties["words"] = cell->getParam(ID::SIZE).as_int();
+ match_properties["abits"] = cell->getParam(ID::ABITS).as_int();
+ match_properties["dbits"] = cell->getParam(ID::WIDTH).as_int();
+ match_properties["wports"] = cell->getParam(ID::WR_PORTS).as_int();
+ match_properties["rports"] = cell->getParam(ID::RD_PORTS).as_int();
match_properties["bits"] = match_properties["words"] * match_properties["dbits"];
match_properties["ports"] = match_properties["wports"] + match_properties["rports"];
@@ -1079,9 +1102,6 @@ void handle_cell(Cell *cell, const rules_t &rules)
auto &bram = rules.brams.at(match.name).at(vi);
bool or_next_if_better = match.or_next_if_better || vi+1 < GetSize(rules.brams.at(match.name));
- if (failed_brams.count(pair<IdString, int>(bram.name, bram.variant)))
- continue;
-
int avail_rd_ports = 0;
int avail_wr_ports = 0;
for (int j = 0; j < bram.groups; j++) {
@@ -1117,6 +1137,9 @@ void handle_cell(Cell *cell, const rules_t &rules)
int efficiency = (100 * match_properties["bits"]) / (dups * cells * bram.dbits * (1 << bram.abits));
match_properties["efficiency"] = efficiency;
+ if (failed_brams.count(pair<IdString, int>(bram.name, bram.variant)))
+ goto next_match_rule;
+
log(" Metrics for %s: awaste=%d dwaste=%d bwaste=%d waste=%d efficiency=%d\n",
log_id(match.name), awaste, dwaste, bwaste, waste, efficiency);
@@ -1167,7 +1190,7 @@ void handle_cell(Cell *cell, const rules_t &rules)
}
else if (!exists)
continue;
- if (it->second != value)
+ if (rules.map_case(it->second) != value)
continue;
found = true;
break;
@@ -1179,7 +1202,7 @@ void handle_cell(Cell *cell, const rules_t &rules)
ss << "!";
IdString key = std::get<1>(sums.front());
ss << log_id(key);
- const Const &value = std::get<2>(sums.front());
+ const Const &value = rules.map_case(std::get<2>(sums.front()));
if (exists && value != Const(1))
ss << "=\"" << value.decode_string() << "\"";
@@ -1252,8 +1275,13 @@ struct MemoryBramPass : public Pass {
log("The given rules file describes the available resources and how they should be\n");
log("used.\n");
log("\n");
- log("The rules file contains a set of block ram description and a sequence of match\n");
- log("rules. A block ram description looks like this:\n");
+ log("The rules file contains configuration options, a set of block ram description\n");
+ log("and a sequence of match rules.\n");
+ log("\n");
+ log("The option 'attr_icase' configures how attribute values are matched. The value 0\n");
+ log("means case-sensitive, 1 means case-insensitive.\n");
+ log("\n");
+ log("A block ram description looks like this:\n");
log("\n");
log(" bram RAMB1024X32 # name of BRAM cell\n");
log(" init 1 # set to '1' if BRAM can be initialized\n");
@@ -1357,7 +1385,7 @@ struct MemoryBramPass : public Pass {
for (auto mod : design->selected_modules())
for (auto cell : mod->selected_cells())
- if (cell->type == "$mem")
+ if (cell->type == ID($mem))
handle_cell(cell, rules);
}
} MemoryBramPass;