aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2021-05-13 11:31:03 +0100
committergatecat <gatecat@ds0.me>2021-05-21 10:00:35 +0100
commitbae83857a3bfe533a519c750f611e0e73c7ce4ef (patch)
tree15e0603cb5112d071d41992533b866e998860539
parent64f5b1d031960b779ca788d5fc92843c2213a045 (diff)
downloadnextpnr-bae83857a3bfe533a519c750f611e0e73c7ce4ef.tar.gz
nextpnr-bae83857a3bfe533a519c750f611e0e73c7ce4ef.tar.bz2
nextpnr-bae83857a3bfe533a519c750f611e0e73c7ce4ef.zip
interchange: Add macro parameter mapping
Signed-off-by: gatecat <gatecat@ds0.me>
-rw-r--r--fpga_interchange/examples/tests/lutram/lutram.v4
-rw-r--r--fpga_interchange/macros.cc52
2 files changed, 53 insertions, 3 deletions
diff --git a/fpga_interchange/examples/tests/lutram/lutram.v b/fpga_interchange/examples/tests/lutram/lutram.v
index be5728f8..f38197d4 100644
--- a/fpga_interchange/examples/tests/lutram/lutram.v
+++ b/fpga_interchange/examples/tests/lutram/lutram.v
@@ -7,7 +7,9 @@ module top (
input wire [15:0] sw,
output wire [15:0] led
);
- RAM128X1D ram_i (
+ RAM128X1D #(
+ .INIT(128'hFFEEDDCCBBAA99887766554433221100)
+ ) ram_i (
.WCLK(clk),
.A(sw[6:0]),
.DPRA(sw[13:7]),
diff --git a/fpga_interchange/macros.cc b/fpga_interchange/macros.cc
index 577671fa..eee35d9f 100644
--- a/fpga_interchange/macros.cc
+++ b/fpga_interchange/macros.cc
@@ -34,6 +34,15 @@ static const MacroPOD *lookup_macro(const ChipInfoPOD *chip, IdString cell_type)
return nullptr;
}
+static const MacroExpansionPOD *lookup_macro_rules(const ChipInfoPOD *chip, IdString cell_type)
+{
+ for (const auto &rule : chip->macro_rules) {
+ if (IdString(rule.prim_name) == cell_type)
+ return &rule;
+ }
+ return nullptr;
+}
+
static IdString derived_name(Context *ctx, IdString base_name, IdString suffix)
{
return ctx->id(stringf("%s/%s", base_name.c_str(ctx), suffix.c_str(ctx)));
@@ -53,7 +62,8 @@ void Arch::expand_macros()
// Expand cells
for (auto cell : cells) {
// TODO: consult exception map
- const MacroPOD *macro = lookup_macro(chip_info, cell->type);
+ const MacroExpansionPOD *exp = lookup_macro_rules(chip_info, cell->type);
+ const MacroPOD *macro = lookup_macro(chip_info, exp ? IdString(exp->macro_name) : cell->type);
if (macro == nullptr)
continue;
// Create child instances
@@ -94,7 +104,45 @@ void Arch::expand_macros()
connect_port(ctx, net, inst_cell, port_name);
}
}
- // TODO: apply parameter rules from exception map
+
+ if (exp != nullptr) {
+ // Convert parameters, according to the exception rules
+ for (const auto &param_rule : exp->param_rules) {
+ IdString prim_param(param_rule.prim_param);
+ if (!cell->params.count(prim_param))
+ continue;
+ const auto &prim_param_val = cell->params.at(prim_param);
+ IdString inst_name = derived_name(ctx, cell->name, IdString(param_rule.inst_name));
+ CellInfo *inst_cell = ctx->cells.at(inst_name).get();
+ IdString inst_param(param_rule.inst_param);
+ if (param_rule.rule_type == PARAM_MAP_COPY) {
+ inst_cell->params[inst_param] = prim_param_val;
+ } else if (param_rule.rule_type == PARAM_MAP_SLICE) {
+ auto prim_bits = cell_parameters.parse_int_like(ctx, cell->type, prim_param, prim_param_val);
+ Property value(0, param_rule.slice_bits.ssize());
+ for (int i = 0; i < param_rule.slice_bits.ssize(); i++) {
+ size_t bit = param_rule.slice_bits[i];
+ if (bit >= prim_bits.size())
+ continue;
+ value.str.at(i) = prim_bits.get(bit) ? Property::S1 : Property::S0;
+ }
+ inst_cell->params[inst_param] = value;
+ } else if (param_rule.rule_type == PARAM_MAP_TABLE) {
+ const std::string &prim_str = prim_param_val.as_string();
+ IdString prim_id = ctx->id(prim_str);
+ for (auto &tbl_entry : param_rule.map_table) {
+ if (IdString(tbl_entry.key) == prim_id) {
+ inst_cell->params[inst_param] = IdString(tbl_entry.value).str(ctx);
+ break;
+ }
+ }
+ if (!inst_cell->params.count(inst_param))
+ log_error("Unsupported value '%s' for property '%s' of cell %s:%s\n", prim_str.c_str(),
+ ctx->nameOf(prim_param), ctx->nameOf(cell), ctx->nameOf(cell->type));
+ }
+ }
+ }
+
// Remove the now-expanded cell, but first make sure we don't leave behind any dangling references
for (const auto &port : cell->ports)
if (port.second.net != nullptr)