From b8455f20e2bf431b5cbfba98269489c5c13c872b Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 7 Aug 2019 14:47:01 +0100 Subject: json: Group bus ports in backend Signed-off-by: David Shah --- json/jsonwrite.cc | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index 46cb0b72..1229957b 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -66,6 +66,59 @@ void write_parameters(std::ostream &f, Context *ctx, const std::unordered_map bits; + PortType dir; +}; + +std::vector group_ports(Context *ctx) +{ + std::vector groups; + std::unordered_map base_to_group; + for (auto &pair : ctx->ports) { + std::string name = pair.second.name.str(ctx); + if ((name.back() != ']') || (name.find('[') == std::string::npos)) { + groups.push_back({name, {pair.first.index}, pair.second.type}); + } else { + int off1 = int(name.find_last_of('[')); + std::string basename = name.substr(0, off1); + int index = std::stoi(name.substr(off1 + 1, name.size() - (off1 + 2))); + + if (!base_to_group.count(basename)) { + base_to_group[basename] = groups.size(); + groups.push_back({basename, std::vector(index + 1, -1), pair.second.type}); + } + + auto &grp = groups.at(base_to_group[basename]); + if (int(grp.bits.size()) <= index) + grp.bits.resize(index + 1, -1); + NPNR_ASSERT(grp.bits.at(index) == -1); + grp.bits.at(index) = pair.first.index; + } + } + return groups; +}; + +std::string format_port_bits(const PortGroup &port) +{ + std::stringstream s; + s << "[ "; + bool first = true; + for (auto bit : port.bits) { + if (!first) + s << ", "; + if (bit == -1) + s << "\"x\""; + else + s << bit; + first = false; + } + s << " ]"; + return s.str(); +} + void write_module(std::ostream &f, Context *ctx) { auto val = ctx->attrs.find(ctx->id("module")); @@ -80,14 +133,15 @@ void write_module(std::ostream &f, Context *ctx) write_parameters(f, ctx, ctx->attrs, true); f << stringf("\n },\n"); f << stringf(" \"ports\": {"); + + auto ports = group_ports(ctx); bool first = true; - for (auto &pair : ctx->ports) { - auto &c = pair.second; + for (auto &port : ports) { f << stringf("%s\n", first ? "" : ","); - f << stringf(" %s: {\n", get_name(c.name, ctx).c_str()); + f << stringf(" %s: {\n", get_string(port.name).c_str()); f << stringf(" \"direction\": \"%s\",\n", - c.type == PORT_IN ? "input" : c.type == PORT_INOUT ? "inout" : "output"); - f << stringf(" \"bits\": [ %d ]\n", pair.first.index); + port.dir == PORT_IN ? "input" : port.dir == PORT_INOUT ? "inout" : "output"); + f << stringf(" \"bits\": %s\n", format_port_bits(port).c_str()); f << stringf(" }"); first = false; } -- cgit v1.2.3