diff options
| -rw-r--r-- | frontend/json/jsonparse.cc | 41 | ||||
| -rw-r--r-- | ice40/cells.cc | 23 | ||||
| -rw-r--r-- | ice40/cells.h | 2 | 
3 files changed, 46 insertions, 20 deletions
diff --git a/frontend/json/jsonparse.cc b/frontend/json/jsonparse.cc index cacc57ea..b3d6f718 100644 --- a/frontend/json/jsonparse.cc +++ b/frontend/json/jsonparse.cc @@ -663,7 +663,11 @@ static void insert_iobuf(Context *ctx, NetInfo *net, PortType type,          log_info("processing input port %s\n", name.c_str());          iobuf->type = ctx->id("$nextpnr_ibuf");          iobuf->ports[ctx->id("O")] = PortInfo{ctx->id("O"), net, PORT_OUT}; - +        // Special case: input, etc, directly drives inout +        if (net->driver.cell != nullptr) { +            assert(net->driver.cell->type == ctx->id("$nextpnr_iobuf")); +            net = net->driver.cell->ports.at(ctx->id("I")).net; +        }          assert(net->driver.cell == nullptr);          net->driver.port = ctx->id("O");          net->driver.cell = iobuf; @@ -679,20 +683,22 @@ static void insert_iobuf(Context *ctx, NetInfo *net, PortType type,          log_info("processing inout port %s\n", name.c_str());          iobuf->type = ctx->id("$nextpnr_iobuf");          iobuf->ports[ctx->id("I")] = PortInfo{ctx->id("I"), nullptr, PORT_IN}; -        if (net->driver.cell != NULL) { -            // Split the input and output nets for bidir ports -            NetInfo *net2 = new NetInfo(); -            net2->name = ctx->id("$" + net->name.str(ctx) + "$iobuf_i"); -            net2->driver = net->driver; + +        // Split the input and output nets for bidir ports +        NetInfo *net2 = new NetInfo(); +        net2->name = ctx->id("$" + net->name.str(ctx) + "$iobuf_i"); +        net2->driver = net->driver; +        if (net->driver.cell != nullptr) {              net2->driver.cell->ports[net2->driver.port].net = net2;              net->driver.cell = nullptr; -            ctx->nets[net2->name] = net2; -            iobuf->ports[ctx->id("I")].net = net2; -            PortRef ref; -            ref.cell = iobuf; -            ref.port = ctx->id("I"); -            net2->users.push_back(ref);          } +        ctx->nets[net2->name] = net2; +        iobuf->ports[ctx->id("I")].net = net2; +        PortRef ref; +        ref.cell = iobuf; +        ref.port = ctx->id("I"); +        net2->users.push_back(ref); +          iobuf->ports[ctx->id("O")] = PortInfo{ctx->id("O"), net, PORT_OUT};          assert(net->driver.cell == nullptr);          net->driver.port = ctx->id("O"); @@ -742,11 +748,12 @@ void json_import(Context *ctx, string modname, JsonNode *node)                      int netid = bits->data_array.at(i)->data_number;                      if (netid >= netnames.size())                          netnames.resize(netid + 1); -                    netnames.at(netid) = ctx->id( -                            basename + -                            (num_bits == 1 ? "" : std::string("[") + -                                                          std::to_string(i) + -                                                          std::string("]"))); +                    netnames.at(netid) = +                            ctx->id(basename + +                                    (num_bits == 1 ? "" +                                                   : std::string("[") + +                                                             std::to_string(i) + +                                                             std::string("]")));                  }              }          } diff --git a/ice40/cells.cc b/ice40/cells.cc index e0640f0c..d21d5b3b 100644 --- a/ice40/cells.cc +++ b/ice40/cells.cc @@ -25,7 +25,7 @@  NEXTPNR_NAMESPACE_BEGIN  void add_port(const Context *ctx, CellInfo *cell, std::string name, -                     PortType dir) +              PortType dir)  {      IdString id = ctx->id(name);      cell->ports[id] = PortInfo{id, nullptr, dir}; @@ -179,7 +179,7 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc,      replace_port(dff, "Q", lc, "O");  } -void nxio_to_sb(const Context *ctx, CellInfo *nxio, CellInfo *sbio) +void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio)  {      if (nxio->type == ctx->id("$nextpnr_ibuf")) {          sbio->params[ctx->id("PIN_TYPE")] = "1"; @@ -190,9 +190,28 @@ void nxio_to_sb(const Context *ctx, CellInfo *nxio, CellInfo *sbio)      } else if (nxio->type == ctx->id("$nextpnr_obuf")) {          sbio->params[ctx->id("PIN_TYPE")] = "25";          replace_port(nxio, "I", sbio, "D_OUT_0"); +    } else if (nxio->type == ctx->id("$nextpnr_iobuf")) { +        // N.B. tristate will be dealt with below +        sbio->params[ctx->id("PIN_TYPE")] = "25"; +        replace_port(nxio, "I", sbio, "D_OUT_0"); +        replace_port(nxio, "O", sbio, "D_IN_0");      } else {          assert(false);      } +    NetInfo *donet = sbio->ports.at(ctx->id("D_OUT_0")).net; +    CellInfo *tbuf = +            net_driven_by(ctx, donet, [] +                          (const Context *ctx, const CellInfo *cell) { +                              return cell->type == ctx->id("$_TBUF_"); +                          }, +                          "Y"); +    if (tbuf) { +        sbio->params[ctx->id("PIN_TYPE")] = "41"; +        replace_port(tbuf, "A", sbio, "D_OUT_0"); +        replace_port(tbuf, "E", sbio, "OUTPUT_ENABLE"); +        ctx->nets.erase(donet->name); +        ctx->cells.erase(tbuf->name); +    }  }  bool is_clock_port(const Context *ctx, const PortRef &port) diff --git a/ice40/cells.h b/ice40/cells.h index bd07563e..f1636410 100644 --- a/ice40/cells.h +++ b/ice40/cells.h @@ -96,7 +96,7 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc,                 bool pass_thru_lut = false);  // Convert a nextpnr IO buffer to a SB_IO -void nxio_to_sb(const Context *ctx, CellInfo *nxio, CellInfo *sbio); +void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio);  // Return true if a net is a global net  bool is_global_net(const Context *ctx, const NetInfo *net);  | 
