diff options
| author | David Shah <davey1576@gmail.com> | 2018-07-18 09:35:40 +0200 | 
|---|---|---|
| committer | David Shah <davey1576@gmail.com> | 2018-07-18 09:35:40 +0200 | 
| commit | f138368e343d0d69b6e1f74d44e13d7097999de6 (patch) | |
| tree | 4029320dd0b01010d72740b137b3ebc5bf398f7b | |
| parent | edf7bd09cf2a27fa1ada1a1e34cbe47c4bf0d48a (diff) | |
| download | nextpnr-f138368e343d0d69b6e1f74d44e13d7097999de6.tar.gz nextpnr-f138368e343d0d69b6e1f74d44e13d7097999de6.tar.bz2 nextpnr-f138368e343d0d69b6e1f74d44e13d7097999de6.zip  | |
ecp5: Add simple constant packer
Signed-off-by: David Shah <davey1576@gmail.com>
| -rw-r--r-- | ecp5/archdefs.h | 8 | ||||
| -rw-r--r-- | ecp5/cells.cc | 8 | ||||
| -rw-r--r-- | ecp5/pack.cc | 84 | 
3 files changed, 98 insertions, 2 deletions
diff --git a/ecp5/archdefs.h b/ecp5/archdefs.h index df1add44..941607ba 100644 --- a/ecp5/archdefs.h +++ b/ecp5/archdefs.h @@ -129,8 +129,12 @@ struct DecalId      }  }; -struct ArchNetInfo { }; -struct ArchCellInfo { }; +struct ArchNetInfo +{ +}; +struct ArchCellInfo +{ +};  NEXTPNR_NAMESPACE_END diff --git a/ecp5/cells.cc b/ecp5/cells.cc index 59504735..22e6a8dc 100644 --- a/ecp5/cells.cc +++ b/ecp5/cells.cc @@ -116,6 +116,14 @@ std::unique_ptr<CellInfo> create_ecp5_cell(Context *ctx, IdString type, std::str          add_port(ctx, new_cell.get(), "I", PORT_IN);          add_port(ctx, new_cell.get(), "T", PORT_IN);          add_port(ctx, new_cell.get(), "O", PORT_OUT); +    } else if (type == ctx->id("LUT4")) { +        new_cell->params[ctx->id("INIT")] = "0"; + +        add_port(ctx, new_cell.get(), "A", PORT_IN); +        add_port(ctx, new_cell.get(), "B", PORT_IN); +        add_port(ctx, new_cell.get(), "C", PORT_IN); +        add_port(ctx, new_cell.get(), "D", PORT_IN); +        add_port(ctx, new_cell.get(), "Z", PORT_OUT);      } else {          log_error("unable to create ECP5 cell of type %s", type.c_str(ctx));      } diff --git a/ecp5/pack.cc b/ecp5/pack.cc index c0427d46..47f22e55 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -385,10 +385,94 @@ class Ecp5Packer          cell->ports.at(input).net = nullptr;      } +    // Merge a net into a constant net +    void set_net_constant(const Context *ctx, NetInfo *orig, NetInfo *constnet, bool constval) +    { +        orig->driver.cell = nullptr; +        for (auto user : orig->users) { +            if (user.cell != nullptr) { +                CellInfo *uc = user.cell; +                if (ctx->verbose) +                    log_info("%s user %s\n", orig->name.c_str(ctx), uc->name.c_str(ctx)); +                if (is_lut(ctx, uc)) { +                    set_lut_input_constant(uc, user.port, constval); +                } else if (is_ff(ctx, uc) && user.port == ctx->id("CE")) { +                    uc->params[ctx->id("CEMUX")] = constval ? "1" : "0"; +                    uc->ports[user.port].net = nullptr; +                } else if (is_ff(ctx, uc) && user.port == ctx->id("LSR") && +                           ((!constval && str_or_default(uc->params, ctx->id("LSRMUX"), "LSR") == "LSR") || +                            (constval && str_or_default(uc->params, ctx->id("LSRMUX"), "LSR") == "INV"))) { +                    uc->ports[user.port].net = nullptr; +                } else { +                    uc->ports[user.port].net = constnet; +                    constnet->users.push_back(user); +                } +            } +        } +        orig->users.clear(); +    } + +    // Pack constants (simple implementation) +    void pack_constants() +    { +        log_info("Packing constants..\n"); + +        std::unique_ptr<CellInfo> gnd_cell = create_ecp5_cell(ctx, ctx->id("LUT4"), "$PACKER_GND"); +        gnd_cell->params[ctx->id("LUT_INIT")] = "0"; +        std::unique_ptr<NetInfo> gnd_net = std::unique_ptr<NetInfo>(new NetInfo); +        gnd_net->name = ctx->id("$PACKER_GND_NET"); +        gnd_net->driver.cell = gnd_cell.get(); +        gnd_net->driver.port = ctx->id("Z"); +        gnd_cell->ports.at(ctx->id("Z")).net = gnd_net.get(); + +        std::unique_ptr<CellInfo> vcc_cell = create_ecp5_cell(ctx, ctx->id("LUT4"), "$PACKER_VCC"); +        vcc_cell->params[ctx->id("LUT_INIT")] = "65535"; +        std::unique_ptr<NetInfo> vcc_net = std::unique_ptr<NetInfo>(new NetInfo); +        vcc_net->name = ctx->id("$PACKER_VCC_NET"); +        vcc_net->driver.cell = vcc_cell.get(); +        vcc_net->driver.port = ctx->id("Z"); +        vcc_cell->ports.at(ctx->id("Z")).net = vcc_net.get(); + +        std::vector<IdString> dead_nets; + +        bool gnd_used = false, vcc_used = false; + +        for (auto net : sorted(ctx->nets)) { +            NetInfo *ni = net.second; +            if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) { +                IdString drv_cell = ni->driver.cell->name; +                set_net_constant(ctx, ni, gnd_net.get(), false); +                gnd_used = true; +                dead_nets.push_back(net.first); +                ctx->cells.erase(drv_cell); +            } else if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("VCC")) { +                IdString drv_cell = ni->driver.cell->name; +                set_net_constant(ctx, ni, vcc_net.get(), true); +                vcc_used = true; +                dead_nets.push_back(net.first); +                ctx->cells.erase(drv_cell); +            } +        } + +        if (gnd_used) { +            ctx->cells[gnd_cell->name] = std::move(gnd_cell); +            ctx->nets[gnd_net->name] = std::move(gnd_net); +        } +        if (vcc_used) { +            ctx->cells[vcc_cell->name] = std::move(vcc_cell); +            ctx->nets[vcc_net->name] = std::move(vcc_net); +        } + +        for (auto dn : dead_nets) { +            ctx->nets.erase(dn); +        } +    } +    public:      void pack()      {          pack_io(); +        pack_constants();          find_lutff_pairs();          pack_lut5s();          pair_luts();  | 
