From 0aec418ee3577f0860554a0879606f9e5449e955 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 13 Jun 2018 09:42:33 +0200 Subject: Adding IO buffer insertion function to JSON frontend Signed-off-by: David Shah --- frontend/json/jsonparse.cc | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'frontend') diff --git a/frontend/json/jsonparse.cc b/frontend/json/jsonparse.cc index 3f965ce4..f16d4eec 100644 --- a/frontend/json/jsonparse.cc +++ b/frontend/json/jsonparse.cc @@ -640,6 +640,61 @@ void json_import_cell(Design *design, string modname, JsonNode *cell_node, // check_all_nets_driven(design); } +static void insert_iobuf(Design *design, NetInfo *net, PortType type, + string name) +{ + // Instantiate a architecture-independent IO buffer connected to a given + // net, of a given type, and named after the IO port. + // + // During packing, this generic IO buffer will be converted to an + // architecure primitive. + // + CellInfo *iobuf = new CellInfo(); + iobuf->name = name; + std::copy(net->attrs.begin(), net->attrs.end(), + std::inserter(iobuf->attrs, iobuf->attrs.begin())); + if (type == PORT_IN) { + iobuf->type = "$nextpnr_ibuf"; + iobuf->ports["O"] = PortInfo{"O", net, PORT_OUT}; + + assert(net->driver.cell == nullptr); + net->driver.port = "O"; + net->driver.cell = iobuf; + } else if (type == PORT_OUT) { + iobuf->type == "$nextpnr_obuf"; + iobuf->ports["I"] = PortInfo{"I", net, PORT_IN}; + PortRef ref; + ref.cell = iobuf; + ref.port = "I"; + net->users.push_back(ref); + } else if (type == PORT_INOUT) { + iobuf->type == "$nextpnr_iobuf"; + iobuf->ports["I"] = PortInfo{"I", nullptr, PORT_IN}; + if (net->driver.cell != NULL) { + // Split the input and output nets for bidir ports + NetInfo *net2 = new NetInfo(); + net2->name = "$" + net->name.str() + "$iobuf_i"; + net2->driver = net->driver; + net2->driver.cell->ports[net2->driver.port].net = net2; + net->driver.cell = nullptr; + design->nets[net2->name] = net2; + iobuf->ports["I"].net = net2; + PortRef ref; + ref.cell = iobuf; + ref.port = "I"; + net2->users.push_back(ref); + + } + iobuf->ports["O"] = PortInfo{"O", net, PORT_OUT}; + assert(net->driver.cell == nullptr); + net->driver.port = "O"; + net->driver.cell = iobuf; + } else { + assert(false); + } + design->cells[iobuf->name] = iobuf; +} + void json_import(Design *design, string modname, JsonNode *node) { if (is_blackbox(node)) -- cgit v1.2.3 From a34c790b6a3e529fd8deae490d848d0d6d22e83d Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 13 Jun 2018 10:06:31 +0200 Subject: frontend/json: Refactor port importer Signed-off-by: David Shah --- frontend/json/jsonparse.cc | 69 +++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 37 deletions(-) (limited to 'frontend') diff --git a/frontend/json/jsonparse.cc b/frontend/json/jsonparse.cc index f16d4eec..9f4c67c2 100644 --- a/frontend/json/jsonparse.cc +++ b/frontend/json/jsonparse.cc @@ -341,24 +341,25 @@ void json_import_cell_params(Design *design, string &modname, CellInfo *cell, modname.c_str()); } -void json_import_cell_ports(Design *design, string &modname, CellInfo *cell, - string &port_name, JsonNode *dir_node, - JsonNode *wire_group_node) +template +void json_import_ports(Design *design, const string &modname, + const string &obj_name, const string &port_name, + JsonNode *dir_node, JsonNode *wire_group_node, F visitor) { - // Examine and connect a single port of the given cell to its nets, - // generating them as necessary - + // Examine a port of a cell or the design. For every bit of the port, + // the connected net will be processed and `visitor` will be called + // with (PortType dir, std::string name, NetInfo *net) assert(dir_node); if (json_debug) log_info(" Examining port %s, node %s\n", port_name.c_str(), - cell->name.c_str()); + obj_name.c_str()); if (!wire_group_node) log_error("JSON no connection match " "for port_direction \'%s\' of node \'%s\' " "in module \'%s\'\n", - port_name.c_str(), cell->name.c_str(), modname.c_str()); + port_name.c_str(), obj_name.c_str(), modname.c_str()); assert(wire_group_node); @@ -377,7 +378,7 @@ void json_import_cell_ports(Design *design, string &modname, CellInfo *cell, else log_error("JSON unknown port direction \'%s\' in node \'%s\' " "of module \'%s\'\n", - dir_node->data_string.c_str(), cell->name.c_str(), + dir_node->data_string.c_str(), obj_name.c_str(), modname.c_str()); // // Find an update, or create a net to connect @@ -398,18 +399,12 @@ void json_import_cell_ports(Design *design, string &modname, CellInfo *cell, // There is/are no connections to this port. // // Create the port, but leave the net NULL - PortInfo this_port; - - // - this_port.name = port_info.name; - this_port.type = port_info.type; - this_port.net = NULL; - cell->ports[this_port.name] = this_port; + visitor(port_info.type, port_info.name, nullptr); if (json_debug) log_info(" Port \'%s\' has no connection in \'%s\'\n", - this_port.name.c_str(), cell->name.c_str()); + port_info.name.c_str(), obj_name.c_str()); } else for (int index = 0; index < wire_group_node->data_array.size(); @@ -417,13 +412,10 @@ void json_import_cell_ports(Design *design, string &modname, CellInfo *cell, // JsonNode *wire_node; PortInfo this_port; - PortRef port_ref; bool const_input = false; IdString net_id; // wire_node = wire_group_node->data_array[index]; - port_ref.cell = cell; - // // Pick a name for this port if (is_bus) @@ -433,8 +425,6 @@ void json_import_cell_ports(Design *design, string &modname, CellInfo *cell, this_port.name = port_info.name; this_port.type = port_info.type; - port_ref.port = this_port.name; - if (wire_node->type == 'N') { int net_num; @@ -500,7 +490,7 @@ void json_import_cell_ports(Design *design, string &modname, CellInfo *cell, "\'%s\' of port \'%s\' " "in cell \'%s\' of module \'%s\'\n", wire_node->data_string.c_str(), - port_name.c_str(), cell->name.c_str(), + port_name.c_str(), obj_name.c_str(), modname.c_str()); } else @@ -511,17 +501,8 @@ void json_import_cell_ports(Design *design, string &modname, CellInfo *cell, if (json_debug) log_info(" Inserting port \'%s\' into cell \'%s\'\n", - this_port.name.c_str(), cell->name.c_str()); - - this_port.net = this_net; - - cell->ports[this_port.name] = this_port; - - if (this_port.type == PORT_OUT) { - assert(this_net->driver.cell == NULL); - this_net->driver = port_ref; - } else - this_net->users.push_back(port_ref); + this_port.name.c_str(), obj_name.c_str()); + visitor(this_port.type, this_port.name, this_net); if (design->nets.count(this_net->name) == 0) design->nets[this_net->name] = this_net; @@ -632,8 +613,23 @@ void json_import_cell(Design *design, string modname, JsonNode *cell_node, dir_node = pdir_node->data_dict.at(port_name); wire_group_node = connections->data_dict.at(port_name); - json_import_cell_ports(design, modname, cell, port_name, dir_node, - wire_group_node); + json_import_ports( + design, modname, cell->name, port_name, dir_node, + wire_group_node, + [cell](PortType type, const std::string &name, NetInfo *net) { + cell->ports[name] = PortInfo{name, net, type}; + PortRef pr; + pr.cell = cell; + pr.port = name; + if (net != nullptr) { + if (type == PORT_IN) { + net->users.push_back(pr); + } else if (type == PORT_OUT) { + assert(net->driver.cell == nullptr); + net->driver = pr; + } + } + }); } design->cells[cell->name] = cell; @@ -683,7 +679,6 @@ static void insert_iobuf(Design *design, NetInfo *net, PortType type, ref.cell = iobuf; ref.port = "I"; net2->users.push_back(ref); - } iobuf->ports["O"] = PortInfo{"O", net, PORT_OUT}; assert(net->driver.cell == nullptr); -- cgit v1.2.3 From ddf549b117987c1e52412b58531c48a6050b51d1 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 13 Jun 2018 10:21:31 +0200 Subject: frontend/son: Insert generic IO buffers for top level IO Signed-off-by: David Shah --- frontend/json/jsonparse.cc | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) (limited to 'frontend') diff --git a/frontend/json/jsonparse.cc b/frontend/json/jsonparse.cc index 9f4c67c2..df3a298e 100644 --- a/frontend/json/jsonparse.cc +++ b/frontend/json/jsonparse.cc @@ -622,7 +622,7 @@ void json_import_cell(Design *design, string modname, JsonNode *cell_node, pr.cell = cell; pr.port = name; if (net != nullptr) { - if (type == PORT_IN) { + if (type == PORT_IN || type == PORT_INOUT) { net->users.push_back(pr); } else if (type == PORT_OUT) { assert(net->driver.cell == nullptr); @@ -637,7 +637,7 @@ void json_import_cell(Design *design, string modname, JsonNode *cell_node, } static void insert_iobuf(Design *design, NetInfo *net, PortType type, - string name) + const string &name) { // Instantiate a architecture-independent IO buffer connected to a given // net, of a given type, and named after the IO port. @@ -650,6 +650,7 @@ static void insert_iobuf(Design *design, NetInfo *net, PortType type, std::copy(net->attrs.begin(), net->attrs.end(), std::inserter(iobuf->attrs, iobuf->attrs.begin())); if (type == PORT_IN) { + log_info("processing input port %s\n", name.c_str()); iobuf->type = "$nextpnr_ibuf"; iobuf->ports["O"] = PortInfo{"O", net, PORT_OUT}; @@ -657,14 +658,16 @@ static void insert_iobuf(Design *design, NetInfo *net, PortType type, net->driver.port = "O"; net->driver.cell = iobuf; } else if (type == PORT_OUT) { - iobuf->type == "$nextpnr_obuf"; + log_info("processing output port %s\n", name.c_str()); + iobuf->type = "$nextpnr_obuf"; iobuf->ports["I"] = PortInfo{"I", net, PORT_IN}; PortRef ref; ref.cell = iobuf; ref.port = "I"; net->users.push_back(ref); } else if (type == PORT_INOUT) { - iobuf->type == "$nextpnr_iobuf"; + log_info("processing inout port %s\n", name.c_str()); + iobuf->type = "$nextpnr_iobuf"; iobuf->ports["I"] = PortInfo{"I", nullptr, PORT_IN}; if (net->driver.cell != NULL) { // Split the input and output nets for bidir ports @@ -690,6 +693,14 @@ static void insert_iobuf(Design *design, NetInfo *net, PortType type, design->cells[iobuf->name] = iobuf; } +void json_import_toplevel_port(Design *design, const string &modname, const string& portname, JsonNode *node) { + JsonNode *dir_node = node->data_dict.at("direction"); + JsonNode *nets_node = node->data_dict.at("bits"); + json_import_ports(design, modname, "Top Level IO", portname, dir_node, nets_node, [design](PortType type, const std::string &name, NetInfo *net){ + insert_iobuf(design, net, type, name); + }); +} + void json_import(Design *design, string modname, JsonNode *node) { if (is_blackbox(node)) @@ -715,6 +726,21 @@ void json_import(Design *design, string modname, JsonNode *node) } } + if (node->data_dict.count("ports")) { + JsonNode *ports_parent = node->data_dict.at("ports"); + + // N.B. ports must be imported after cells for tristate behaviour + // to be correct + // Loop through all ports + for (int portid = 0; portid < GetSize(ports_parent->data_dict_keys); + portid++) { + JsonNode *here, *param_node; + + here = ports_parent->data_dict.at( + ports_parent->data_dict_keys[portid]); + json_import_toplevel_port(design, modname, ports_parent->data_dict_keys[portid], here); + } + } check_all_nets_driven(design); } -- cgit v1.2.3 From a76f5c5678980c8b2e958252a68ba03676d63229 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 13 Jun 2018 10:50:05 +0200 Subject: Remove IO buffers when fed by SB_IO Signed-off-by: David Shah --- frontend/json/jsonparse.cc | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'frontend') diff --git a/frontend/json/jsonparse.cc b/frontend/json/jsonparse.cc index df3a298e..79ee0a4d 100644 --- a/frontend/json/jsonparse.cc +++ b/frontend/json/jsonparse.cc @@ -693,12 +693,16 @@ static void insert_iobuf(Design *design, NetInfo *net, PortType type, design->cells[iobuf->name] = iobuf; } -void json_import_toplevel_port(Design *design, const string &modname, const string& portname, JsonNode *node) { +void json_import_toplevel_port(Design *design, const string &modname, + const string &portname, JsonNode *node) +{ JsonNode *dir_node = node->data_dict.at("direction"); JsonNode *nets_node = node->data_dict.at("bits"); - json_import_ports(design, modname, "Top Level IO", portname, dir_node, nets_node, [design](PortType type, const std::string &name, NetInfo *net){ - insert_iobuf(design, net, type, name); - }); + json_import_ports( + design, modname, "Top Level IO", portname, dir_node, nets_node, + [design](PortType type, const std::string &name, NetInfo *net) { + insert_iobuf(design, net, type, name); + }); } void json_import(Design *design, string modname, JsonNode *node) @@ -738,7 +742,9 @@ void json_import(Design *design, string modname, JsonNode *node) here = ports_parent->data_dict.at( ports_parent->data_dict_keys[portid]); - json_import_toplevel_port(design, modname, ports_parent->data_dict_keys[portid], here); + json_import_toplevel_port(design, modname, + ports_parent->data_dict_keys[portid], + here); } } check_all_nets_driven(design); -- cgit v1.2.3