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());
|
log_info("processing input port %s\n", name.c_str());
|
||||||
iobuf->type = ctx->id("$nextpnr_ibuf");
|
iobuf->type = ctx->id("$nextpnr_ibuf");
|
||||||
iobuf->ports[ctx->id("O")] = PortInfo{ctx->id("O"), net, PORT_OUT};
|
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);
|
assert(net->driver.cell == nullptr);
|
||||||
net->driver.port = ctx->id("O");
|
net->driver.port = ctx->id("O");
|
||||||
net->driver.cell = iobuf;
|
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());
|
log_info("processing inout port %s\n", name.c_str());
|
||||||
iobuf->type = ctx->id("$nextpnr_iobuf");
|
iobuf->type = ctx->id("$nextpnr_iobuf");
|
||||||
iobuf->ports[ctx->id("I")] = PortInfo{ctx->id("I"), nullptr, PORT_IN};
|
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
|
// Split the input and output nets for bidir ports
|
||||||
NetInfo *net2 = new NetInfo();
|
NetInfo *net2 = new NetInfo();
|
||||||
net2->name = ctx->id("$" + net->name.str(ctx) + "$iobuf_i");
|
net2->name = ctx->id("$" + net->name.str(ctx) + "$iobuf_i");
|
||||||
net2->driver = net->driver;
|
net2->driver = net->driver;
|
||||||
|
if (net->driver.cell != nullptr) {
|
||||||
net2->driver.cell->ports[net2->driver.port].net = net2;
|
net2->driver.cell->ports[net2->driver.port].net = net2;
|
||||||
net->driver.cell = nullptr;
|
net->driver.cell = nullptr;
|
||||||
|
}
|
||||||
ctx->nets[net2->name] = net2;
|
ctx->nets[net2->name] = net2;
|
||||||
iobuf->ports[ctx->id("I")].net = net2;
|
iobuf->ports[ctx->id("I")].net = net2;
|
||||||
PortRef ref;
|
PortRef ref;
|
||||||
ref.cell = iobuf;
|
ref.cell = iobuf;
|
||||||
ref.port = ctx->id("I");
|
ref.port = ctx->id("I");
|
||||||
net2->users.push_back(ref);
|
net2->users.push_back(ref);
|
||||||
}
|
|
||||||
iobuf->ports[ctx->id("O")] = PortInfo{ctx->id("O"), net, PORT_OUT};
|
iobuf->ports[ctx->id("O")] = PortInfo{ctx->id("O"), net, PORT_OUT};
|
||||||
assert(net->driver.cell == nullptr);
|
assert(net->driver.cell == nullptr);
|
||||||
net->driver.port = ctx->id("O");
|
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;
|
int netid = bits->data_array.at(i)->data_number;
|
||||||
if (netid >= netnames.size())
|
if (netid >= netnames.size())
|
||||||
netnames.resize(netid + 1);
|
netnames.resize(netid + 1);
|
||||||
netnames.at(netid) = ctx->id(
|
netnames.at(netid) =
|
||||||
basename +
|
ctx->id(basename +
|
||||||
(num_bits == 1 ? "" : std::string("[") +
|
(num_bits == 1 ? ""
|
||||||
|
: std::string("[") +
|
||||||
std::to_string(i) +
|
std::to_string(i) +
|
||||||
std::string("]")));
|
std::string("]")));
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc,
|
|||||||
replace_port(dff, "Q", lc, "O");
|
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")) {
|
if (nxio->type == ctx->id("$nextpnr_ibuf")) {
|
||||||
sbio->params[ctx->id("PIN_TYPE")] = "1";
|
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")) {
|
} else if (nxio->type == ctx->id("$nextpnr_obuf")) {
|
||||||
sbio->params[ctx->id("PIN_TYPE")] = "25";
|
sbio->params[ctx->id("PIN_TYPE")] = "25";
|
||||||
replace_port(nxio, "I", sbio, "D_OUT_0");
|
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 {
|
} else {
|
||||||
assert(false);
|
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)
|
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);
|
bool pass_thru_lut = false);
|
||||||
|
|
||||||
// Convert a nextpnr IO buffer to a SB_IO
|
// 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
|
// Return true if a net is a global net
|
||||||
bool is_global_net(const Context *ctx, const NetInfo *net);
|
bool is_global_net(const Context *ctx, const NetInfo *net);
|
||||||
|
Loading…
Reference in New Issue
Block a user