ice40: Adding support for tristate IO
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
ec2792764a
commit
e3519ddfcd
@ -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;
|
||||
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);
|
||||
}
|
||||
|
||||
iobuf->ports[ctx->id("O")] = PortInfo{ctx->id("O"), net, PORT_OUT};
|
||||
assert(net->driver.cell == nullptr);
|
||||
net->driver.port = ctx->id("O");
|
||||
@ -742,9 +748,10 @@ 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("[") +
|
||||
netnames.at(netid) =
|
||||
ctx->id(basename +
|
||||
(num_bits == 1 ? ""
|
||||
: std::string("[") +
|
||||
std::to_string(i) +
|
||||
std::string("]")));
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user