From d49eb2ba40a4c1eb429d67c811c5a5ebc1c22015 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Apr 2019 09:27:34 -0700 Subject: [PATCH 01/12] Changes to cope with YosysHQ/yosys#943 --- json/jsonparse.cc | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/json/jsonparse.cc b/json/jsonparse.cc index a0479c2e..5d77c101 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -285,7 +285,7 @@ void vcc_net(Context *ctx, NetInfo *net) // true, false otherwise bool is_blackbox(JsonNode *node) { - JsonNode *attr_node, *bbox_node; + JsonNode *attr_node, *bbox_node = nullptr, *wbox_node = nullptr; if (node->data_dict.count("attributes") == 0) return false; @@ -296,14 +296,19 @@ bool is_blackbox(JsonNode *node) return false; if (GetSize(attr_node->data_dict) == 0) return false; - if (attr_node->data_dict.count("blackbox") == 0) + if (attr_node->data_dict.count("blackbox")) + bbox_node = attr_node->data_dict.at("blackbox"); + if (attr_node->data_dict.count("whitebox")) + wbox_node = attr_node->data_dict.at("whitebox"); + if (bbox_node == NULL && wbox_node == NULL) return false; - bbox_node = attr_node->data_dict.at("blackbox"); - if (bbox_node == NULL) + if (bbox_node && bbox_node->type != 'N') + log_error("JSON module blackbox attribute value is not a number\n"); + if (bbox_node && bbox_node->data_number == 0) return false; - if (bbox_node->type != 'N') - log_error("JSON module blackbox is not a number\n"); - if (bbox_node->data_number == 0) + if (wbox_node && wbox_node->type != 'N') + log_error("JSON module whitebox attribute value is not a number\n"); + if (wbox_node && wbox_node->data_number == 0) return false; return true; } From bfe4c50d8890bf8d8b65bb6f1fc894596721cd73 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 20 May 2019 11:50:23 -0700 Subject: [PATCH 02/12] Add link to arXiv paper --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index b2144ce5..dc57c6bd 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,9 @@ We hope to see Xilinx 7 Series thanks to supported in the future. We would love your help in developing this awesome new project! +A brief (academic) paper describing the Yosys+nextpnr flow can be found +on [arXiv](https://arxiv.org/abs/1903.10407). + Here is a screenshot of nextpnr for iCE40. Build instructions and [getting started notes](#getting-started) can be found below. From f3339961feea47bce48e400c0eda8468b2e0356e Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 4 Jun 2019 13:15:23 +0000 Subject: [PATCH 03/12] Fix missing \n in log statement. --- common/timing.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/timing.cc b/common/timing.cc index 2ce9eea3..09d15758 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -752,7 +752,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p } if (clock_reports.empty()) { - log_warning("No clocks found in design"); + log_warning("No clocks found in design\n"); } std::sort(xclock_paths.begin(), xclock_paths.end(), [ctx](const ClockPair &a, const ClockPair &b) { From 187db92b0571b87360516598e88f36cdb1f33349 Mon Sep 17 00:00:00 2001 From: David Shah Date: Sat, 8 Jun 2019 10:52:37 +0100 Subject: [PATCH 04/12] ecp5: Improve error message for bad chars in BRAM init strings Signed-off-by: David Shah --- ecp5/bitstream.cc | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index a9c82524..d549a727 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -134,7 +134,7 @@ inline int chtohex(char c) return hex.find(c); } -std::vector parse_init_str(const std::string &str, int length) +std::vector parse_init_str(const std::string &str, int length, const char *cellname) { // Parse a string that may be binary or hex std::vector result; @@ -161,7 +161,8 @@ std::vector parse_init_str(const std::string &str, int length) log_error("hex string value too long, expected up to %d bits and found %d.\n", length, int(str.length())); for (int i = 0; i < int(str.length()); i++) { char c = str.at((str.size() - i) - 1); - NPNR_ASSERT(c == '0' || c == '1' || c == 'X' || c == 'x'); + if (c != '0' && c != '1' && c != 'X' && c != 'x') + log_error("Found illegal character '%c' while processing parameters for cell '%s'\n", c, cellname); result.at(i) = (c == '1'); } } @@ -970,7 +971,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex for (int i = 0; i <= 0x3F; i++) { IdString param = ctx->id("INITVAL_" + fmt_str(std::hex << std::uppercase << std::setw(2) << std::setfill('0') << i)); - auto value = parse_init_str(str_or_default(ci->params, param, "0"), 320); + auto value = parse_init_str(str_or_default(ci->params, param, "0"), 320, ci->name.c_str(ctx)); for (int j = 0; j < 16; j++) { // INIT parameter consists of 16 18-bit words with 2-bit padding int ofs = 20 * j; @@ -1078,17 +1079,21 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex tg.config.add_enum(dsp + ".MASKPAT_SOURCE", str_or_default(ci->params, ctx->id("MASKPAT_SOURCE"), "STATIC")); tg.config.add_word(dsp + ".MASK01", - parse_init_str(str_or_default(ci->params, ctx->id("MASK01"), "0x00000000000000"), 56)); + parse_init_str(str_or_default(ci->params, ctx->id("MASK01"), "0x00000000000000"), 56, + ci->name.c_str(ctx))); tg.config.add_enum(dsp + ".CLK0_DIV", str_or_default(ci->params, ctx->id("CLK0_DIV"), "ENABLED")); tg.config.add_enum(dsp + ".CLK1_DIV", str_or_default(ci->params, ctx->id("CLK1_DIV"), "ENABLED")); tg.config.add_enum(dsp + ".CLK2_DIV", str_or_default(ci->params, ctx->id("CLK2_DIV"), "ENABLED")); tg.config.add_enum(dsp + ".CLK3_DIV", str_or_default(ci->params, ctx->id("CLK3_DIV"), "ENABLED")); tg.config.add_word(dsp + ".MCPAT", - parse_init_str(str_or_default(ci->params, ctx->id("MCPAT"), "0x00000000000000"), 56)); + parse_init_str(str_or_default(ci->params, ctx->id("MCPAT"), "0x00000000000000"), 56, + ci->name.c_str(ctx))); tg.config.add_word(dsp + ".MASKPAT", - parse_init_str(str_or_default(ci->params, ctx->id("MASKPAT"), "0x00000000000000"), 56)); + parse_init_str(str_or_default(ci->params, ctx->id("MASKPAT"), "0x00000000000000"), 56, + ci->name.c_str(ctx))); tg.config.add_word(dsp + ".RNDPAT", - parse_init_str(str_or_default(ci->params, ctx->id("RNDPAT"), "0x00000000000000"), 56)); + parse_init_str(str_or_default(ci->params, ctx->id("RNDPAT"), "0x00000000000000"), 56, + ci->name.c_str(ctx))); tg.config.add_enum(dsp + ".GSR", str_or_default(ci->params, ctx->id("GSR"), "ENABLED")); tg.config.add_enum(dsp + ".RESETMODE", str_or_default(ci->params, ctx->id("RESETMODE"), "SYNC")); tg.config.add_enum(dsp + ".FORCE_ZERO_BARREL_SHIFT", From 88eeafae12b78798f6b886b2d4193b5fa64bac4c Mon Sep 17 00:00:00 2001 From: Simon Schubert <2@0x2c.org> Date: Mon, 10 Jun 2019 11:30:01 +0200 Subject: [PATCH 05/12] ice40: add RGB_DRV/LED_DRV_CUR support for u4k --- ice40/arch.cc | 8 ++++++++ ice40/archdefs.h | 4 ++++ ice40/bitstream.cc | 7 +++++++ ice40/cells.cc | 16 ++++++++++++++++ ice40/cells.h | 4 ++++ ice40/chipdb.py | 2 ++ ice40/constids.inc | 5 +++++ ice40/pack.cc | 35 +++++++++++++++++++++++++++++++---- 8 files changed, 77 insertions(+), 4 deletions(-) diff --git a/ice40/arch.cc b/ice40/arch.cc index d536ad35..80e1fb4c 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -1045,6 +1045,14 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in return TMG_COMB_INPUT; } else if (cell->type == id_SB_WARMBOOT) { return TMG_ENDPOINT; + } else if (cell->type == id_SB_LED_DRV_CUR) { + if (port == id_LEDPU) + return TMG_IGNORE; + return TMG_ENDPOINT; + } else if (cell->type == id_SB_RGB_DRV) { + if (port == id_RGB0 || port == id_RGB1 || port == id_RGB2 || port == id_RGBPU) + return TMG_IGNORE; + return TMG_ENDPOINT; } else if (cell->type == id_SB_RGBA_DRV) { if (port == id_RGB0 || port == id_RGB1 || port == id_RGB2) return TMG_IGNORE; diff --git a/ice40/archdefs.h b/ice40/archdefs.h index 956fcb4c..89591af5 100644 --- a/ice40/archdefs.h +++ b/ice40/archdefs.h @@ -159,6 +159,10 @@ struct ArchCellInfo { bool forPadIn; } gbInfo; + struct + { + bool ledCurConnected; + } ledInfo; }; }; diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index 9b85dff5..d35c43aa 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -610,6 +610,13 @@ void write_asc(const Context *ctx, std::ostream &out) set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_1", write_mode & 0x2); set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_2", read_mode & 0x1); set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_3", read_mode & 0x2); + } else if (cell.second->type == ctx->id("SB_LED_DRV_CUR")) { + set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "LED_DRV_CUR_EN", true, "IpConfig."); + } else if (cell.second->type == ctx->id("SB_RGB_DRV")) { + const std::vector> rgb_params = { + {"RGB0_CURRENT", 6}, {"RGB1_CURRENT", 6}, {"RGB2_CURRENT", 6}}; + configure_extra_cell(config, ctx, cell.second.get(), rgb_params, true, std::string("IpConfig.")); + set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "RGB_DRV_EN", true, "IpConfig."); } else if (cell.second->type == ctx->id("SB_RGBA_DRV")) { const std::vector> rgba_params = { {"CURRENT_MODE", 1}, {"RGB0_CURRENT", 6}, {"RGB1_CURRENT", 6}, {"RGB2_CURRENT", 6}}; diff --git a/ice40/cells.cc b/ice40/cells.cc index 5744fe50..a2abcea4 100644 --- a/ice40/cells.cc +++ b/ice40/cells.cc @@ -260,6 +260,22 @@ std::unique_ptr create_ice_cell(Context *ctx, IdString type, std::stri add_port(ctx, new_cell.get(), "RGB0", PORT_OUT); add_port(ctx, new_cell.get(), "RGB1", PORT_OUT); add_port(ctx, new_cell.get(), "RGB2", PORT_OUT); + } else if (type == ctx->id("SB_LED_DRV_CUR")) { + add_port(ctx, new_cell.get(), "EN", PORT_IN); + add_port(ctx, new_cell.get(), "LEDPU", PORT_OUT); + } else if (type == ctx->id("SB_RGB_DRV")) { + new_cell->params[ctx->id("RGB0_CURRENT")] = "0b000000"; + new_cell->params[ctx->id("RGB1_CURRENT")] = "0b000000"; + new_cell->params[ctx->id("RGB2_CURRENT")] = "0b000000"; + + add_port(ctx, new_cell.get(), "RGBPU", PORT_IN); + add_port(ctx, new_cell.get(), "RGBLEDEN", PORT_IN); + add_port(ctx, new_cell.get(), "RGB0PWM", PORT_IN); + add_port(ctx, new_cell.get(), "RGB1PWM", PORT_IN); + add_port(ctx, new_cell.get(), "RGB2PWM", PORT_IN); + add_port(ctx, new_cell.get(), "RGB0", PORT_OUT); + add_port(ctx, new_cell.get(), "RGB1", PORT_OUT); + add_port(ctx, new_cell.get(), "RGB2", PORT_OUT); } else if (type == ctx->id("SB_LEDDA_IP")) { add_port(ctx, new_cell.get(), "LEDDCS", PORT_IN); add_port(ctx, new_cell.get(), "LEDDCLK", PORT_IN); diff --git a/ice40/cells.h b/ice40/cells.h index ec4d560d..25a98573 100644 --- a/ice40/cells.h +++ b/ice40/cells.h @@ -76,6 +76,10 @@ inline bool is_sb_mac16(const BaseCtx *ctx, const CellInfo *cell) { return cell- inline bool is_sb_rgba_drv(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_RGBA_DRV"); } +inline bool is_sb_rgb_drv(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_RGB_DRV"); } + +inline bool is_sb_led_drv_cur(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_LED_DRV_CUR"); } + inline bool is_sb_ledda_ip(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_LEDDA_IP"); } inline bool is_sb_i2c(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_I2C"); } diff --git a/ice40/chipdb.py b/ice40/chipdb.py index 42ca6ac1..cc7be01f 100644 --- a/ice40/chipdb.py +++ b/ice40/chipdb.py @@ -81,6 +81,8 @@ constids["SPI"] = constids["SB_SPI"] constids["LEDDA_IP"] = constids["SB_LEDDA_IP"] constids["RGBA_DRV"] = constids["SB_RGBA_DRV"] constids["SPRAM"] = constids["ICESTORM_SPRAM"] +constids["LED_DRV_CUR"] = constids["SB_LED_DRV_CUR"] +constids["RGB_DRV"] = constids["SB_RGB_DRV"] with open(args.gfxh) as f: state = 0 diff --git a/ice40/constids.inc b/ice40/constids.inc index 366a3a9d..6aa5c4c0 100644 --- a/ice40/constids.inc +++ b/ice40/constids.inc @@ -355,6 +355,9 @@ X(PWMOUT0) X(PWMOUT1) X(PWMOUT2) +X(LEDPU) +X(EN) +X(RGBPU) X(CURREN) X(RGB0PWM) X(RGB1PWM) @@ -438,6 +441,8 @@ X(IO_I3C) X(SB_LEDDA_IP) X(SB_RGBA_DRV) X(ICESTORM_SPRAM) +X(SB_LED_DRV_CUR) +X(SB_RGB_DRV) // cell parameters X(DFF_ENABLE) diff --git a/ice40/pack.cc b/ice40/pack.cc index 390cbf57..9a77048b 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -450,7 +450,7 @@ static void pack_io(Context *ctx) } else if (ci->type == ctx->id("$nextpnr_obuf")) { NetInfo *net = ci->ports.at(ctx->id("I")).net; sb = net_only_drives(ctx, net, is_ice_iob, ctx->id("PACKAGE_PIN"), true, ci); - if (net && net->driver.cell && is_sb_rgba_drv(ctx, net->driver.cell)) + if (net && net->driver.cell && (is_sb_rgba_drv(ctx, net->driver.cell) || is_sb_rgb_drv(ctx, net->driver.cell))) rgb = net->driver.cell; } if (sb != nullptr) { @@ -476,7 +476,7 @@ static void pack_io(Context *ctx) } } } else if (rgb != nullptr) { - log_info("%s use by SB_RGBA_DRV %s, not creating SB_IO\n", ci->name.c_str(ctx), rgb->name.c_str(ctx)); + log_info("%s use by SB_RGBA_DRV/SB_RGB_DRV %s, not creating SB_IO\n", ci->name.c_str(ctx), rgb->name.c_str(ctx)); disconnect_port(ctx, ci, ctx->id("I")); packed_cells.insert(ci->name); continue; @@ -1038,6 +1038,27 @@ static void pack_special(Context *ctx) std::unordered_set packed_cells; std::vector> new_cells; + // Handle LED_DRV_CUR first to set the ledCurConnected flag before RGB_DRV is handled below. + for (auto cell : sorted(ctx->cells)) { + CellInfo *ci = cell.second; + if (is_sb_led_drv_cur(ctx, ci)) { + /* Force placement (no choices anyway) */ + cell_place_unique(ctx, ci); + + NetInfo *ledpu_net = ci->ports.at(ctx->id("LEDPU")).net; + for (auto &user : ledpu_net->users) { + if (!is_sb_rgb_drv(ctx, user.cell)) { + log_error("SB_LED_DRV_CUR LEDPU port can only be connected to SB_RGB_DRV!\n"); + } else { + user.cell->ledInfo.ledCurConnected = true; + user.cell->ports.at(user.port).net = nullptr; + } + } + ci->ports.erase(ctx->id("LEDPU")); + ctx->nets.erase(ledpu_net->name); + } + } + for (auto cell : sorted(ctx->cells)) { CellInfo *ci = cell.second; if (is_sb_lfosc(ctx, ci)) { @@ -1113,7 +1134,7 @@ static void pack_special(Context *ctx) replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname)); } new_cells.push_back(std::move(packed)); - } else if (is_sb_rgba_drv(ctx, ci)) { + } else if (is_sb_rgba_drv(ctx, ci) || is_sb_rgb_drv(ctx, ci)) { /* Force placement (no choices anyway) */ cell_place_unique(ctx, ci); @@ -1125,14 +1146,20 @@ static void pack_special(Context *ctx) if (net == nullptr) continue; + if ((pi.name != ctx->id("RGB0")) && (pi.name != ctx->id("RGB1")) && (pi.name != ctx->id("RGB2"))) continue; if (net->users.size() > 0) - log_error("SB_RGBA_DRV port connected to more than just package pin !\n"); + log_error("SB_RGB_DRV/SB_RGBA_DRV port connected to more than just package pin !\n"); ctx->nets.erase(net->name); } + + if (is_sb_rgb_drv(ctx, ci) && !ci->ledInfo.ledCurConnected) + log_error("Port RGBPU of SB_RGB_DRV should be driven by port LEDPU of SB_LED_DRV_CUR!\n"); + + ci->ports.erase(ctx->id("RGBPU")); ci->ports.erase(ctx->id("RGB0")); ci->ports.erase(ctx->id("RGB1")); ci->ports.erase(ctx->id("RGB2")); From 7ae64b9477aa98f8f76c3fd23eb9f551758b0d6b Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 21 Jun 2019 10:20:46 +0100 Subject: [PATCH 06/12] ecp5: Reduce cfg.criticalityExponent for now Signed-off-by: David Shah --- ecp5/arch.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 9da8abdf..a27b0860 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -512,7 +512,7 @@ bool Arch::place() if (placer == "heap") { PlacerHeapCfg cfg(getCtx()); - cfg.criticalityExponent = 7; + cfg.criticalityExponent = 4; cfg.ioBufTypes.insert(id_TRELLIS_IO); if (!placer_heap(getCtx(), cfg)) return false; From df8688c227706c88c908c94988b188d686d1c09b Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 21 Jun 2019 10:55:23 +0100 Subject: [PATCH 07/12] ecp5: Delay tweaking for lower speed grades Signed-off-by: David Shah --- ecp5/arch.cc | 6 ++++-- ecp5/arch.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ecp5/arch.cc b/ecp5/arch.cc index a27b0860..91db8d81 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -458,7 +458,7 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const int dx = abs(src_loc.first - dst_loc.first), dy = abs(src_loc.second - dst_loc.second); - return (130 - 25 * args.speed) * + return (120 - 22 * args.speed) * (6 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5))); } @@ -487,7 +487,7 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const int dx = abs(driver_loc.x - sink_loc.x), dy = abs(driver_loc.y - sink_loc.y); - return (130 - 25 * args.speed) * + return (120 - 22 * args.speed) * (6 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5))); } @@ -504,6 +504,8 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay } } +delay_t Arch::getRipupDelayPenalty() const { return 400; } + // ----------------------------------------------------------------------- bool Arch::place() diff --git a/ecp5/arch.h b/ecp5/arch.h index 3de06a42..cee071e7 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -942,7 +942,7 @@ struct Arch : BaseCtx delay_t estimateDelay(WireId src, WireId dst) const; delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const; delay_t getDelayEpsilon() const { return 20; } - delay_t getRipupDelayPenalty() const { return 400; } + delay_t getRipupDelayPenalty() const; float getDelayNS(delay_t v) const { return v * 0.001; } DelayInfo getDelayFromNS(float ns) const { From 5cb9735735ae3a3e93a08951d59578f6104da9a9 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 21 Jun 2019 20:12:24 +0200 Subject: [PATCH 08/12] Add support for upto and offset in JSON files --- json/jsonparse.cc | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/json/jsonparse.cc b/json/jsonparse.cc index eec7041c..6b6c6317 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -337,7 +337,7 @@ static int const_net_idx = 0; template void json_import_ports(Context *ctx, const string &modname, const std::vector &netnames, const string &obj_name, const string &port_name, JsonNode *dir_node, JsonNode *wire_group_node, - F visitor) + bool upto, int start_offset, F visitor) { // 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 @@ -406,8 +406,11 @@ void json_import_ports(Context *ctx, const string &modname, const std::vectordata_array[index]; // // Pick a name for this port + int ndx = index + start_offset; + if (!upto) + ndx = start_offset + wire_group_node->data_array.size() - index - 1; if (is_bus) - this_port.name = ctx->id(port_info.name.str(ctx) + "[" + std::to_string(index) + "]"); + this_port.name = ctx->id(port_info.name.str(ctx) + "[" + std::to_string(ndx) + "]"); else this_port.name = port_info.name; this_port.type = port_info.type; @@ -584,7 +587,7 @@ void json_import_cell(Context *ctx, string modname, const std::vector dir_node = pdir_node->data_dict.at(port_name); wire_group_node = connections->data_dict.at(port_name); - json_import_ports(ctx, modname, netnames, cell->name.str(ctx), port_name, dir_node, wire_group_node, + json_import_ports(ctx, modname, netnames, cell->name.str(ctx), port_name, dir_node, wire_group_node, false, 0, [&cell, ctx](PortType type, const std::string &name, NetInfo *net) { cell->ports[ctx->id(name)] = PortInfo{ctx->id(name), net, type}; PortRef pr; @@ -680,8 +683,20 @@ void json_import_toplevel_port(Context *ctx, const string &modname, const std::v { JsonNode *dir_node = node->data_dict.at("direction"); JsonNode *nets_node = node->data_dict.at("bits"); + bool upto = false; + int start_offset = 0; + if (node->data_dict.count("upto") != 0) { + JsonNode *val = node->data_dict.at("upto"); + if (val->type == 'N') + upto = val->data_number != 0; + } + if (node->data_dict.count("offset") != 0) { + JsonNode *val = node->data_dict.at("offset"); + if (val->type == 'N') + start_offset = val->data_number; + } json_import_ports( - ctx, modname, netnames, "Top Level IO", portname, dir_node, nets_node, + ctx, modname, netnames, "Top Level IO", portname, dir_node, nets_node, upto, start_offset, [ctx](PortType type, const std::string &name, NetInfo *net) { insert_iobuf(ctx, net, type, name); }); } @@ -732,6 +747,18 @@ void json_import(Context *ctx, string modname, JsonNode *node) here = cell_parent->data_dict.at(cell_parent->data_dict_keys[nnid]); std::string basename = cell_parent->data_dict_keys[nnid]; + bool upto = false; + int start_offset = 0; + if (here->data_dict.count("upto") != 0) { + JsonNode *val = here->data_dict.at("upto"); + if (val->type == 'N') + upto = val->data_number != 0; + } + if (here->data_dict.count("offset") != 0) { + JsonNode *val = here->data_dict.at("offset"); + if (val->type == 'N') + start_offset = val->data_number; + } if (here->data_dict.count("bits")) { JsonNode *bits = here->data_dict.at("bits"); assert(bits->type == 'A'); @@ -740,8 +767,11 @@ void json_import(Context *ctx, string modname, JsonNode *node) int netid = bits->data_array.at(i)->data_number; if (netid >= int(netlabels.size())) netlabels.resize(netid + 1); + int ndx = i + start_offset; + if (!upto) + ndx = start_offset + num_bits - i - 1; std::string name = - basename + (num_bits == 1 ? "" : std::string("[") + std::to_string(i) + std::string("]")); + basename + (num_bits == 1 ? "" : std::string("[") + std::to_string(ndx) + std::string("]")); if (prefer_netlabel(name, netlabels.at(netid))) netlabels.at(netid) = name; } From bc1450a5cdc55abbc20775c9372131f97f66afd7 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 22 Jun 2019 09:30:35 +0200 Subject: [PATCH 09/12] Reversed logic --- json/jsonparse.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/json/jsonparse.cc b/json/jsonparse.cc index 6b6c6317..1a98f53f 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -407,7 +407,7 @@ void json_import_ports(Context *ctx, const string &modname, const std::vectordata_array.size() - index - 1; if (is_bus) this_port.name = ctx->id(port_info.name.str(ctx) + "[" + std::to_string(ndx) + "]"); @@ -768,7 +768,7 @@ void json_import(Context *ctx, string modname, JsonNode *node) if (netid >= int(netlabels.size())) netlabels.resize(netid + 1); int ndx = i + start_offset; - if (!upto) + if (upto) ndx = start_offset + num_bits - i - 1; std::string name = basename + (num_bits == 1 ? "" : std::string("[") + std::to_string(ndx) + std::string("]")); From e5c21afc7cc794a7455881262f524d8f276917f7 Mon Sep 17 00:00:00 2001 From: David Shah Date: Sun, 23 Jun 2019 15:01:58 +0100 Subject: [PATCH 10/12] timing: Add missing std::min Signed-off-by: David Shah --- common/timing.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/timing.cc b/common/timing.cc index 09d15758..997061e6 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -546,7 +546,7 @@ struct Timing for (size_t i = 0; i < sink_net->users.size(); i++) { auto &user = sink_net->users.at(i); if (user.cell == drv.cell && user.port == port.first) { - sink_nd.min_required.at(i) = net_min_required - comb_delay.maxDelay(); + sink_nd.min_required.at(i) = std::min(sink_nd.min_required.at(i), net_min_required - comb_delay.maxDelay()); break; } } From 560e3899d8ffe8952cd61067c3b42a4a0b885638 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 24 Jun 2019 10:09:25 +0200 Subject: [PATCH 11/12] Fix formatting --- json/jsonparse.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/json/jsonparse.cc b/json/jsonparse.cc index 1a98f53f..0f229aca 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -750,15 +750,15 @@ void json_import(Context *ctx, string modname, JsonNode *node) bool upto = false; int start_offset = 0; if (here->data_dict.count("upto") != 0) { - JsonNode *val = here->data_dict.at("upto"); - if (val->type == 'N') - upto = val->data_number != 0; - } - if (here->data_dict.count("offset") != 0) { - JsonNode *val = here->data_dict.at("offset"); - if (val->type == 'N') - start_offset = val->data_number; - } + JsonNode *val = here->data_dict.at("upto"); + if (val->type == 'N') + upto = val->data_number != 0; + } + if (here->data_dict.count("offset") != 0) { + JsonNode *val = here->data_dict.at("offset"); + if (val->type == 'N') + start_offset = val->data_number; + } if (here->data_dict.count("bits")) { JsonNode *bits = here->data_dict.at("bits"); assert(bits->type == 'A'); From fa77a5ae4a714e738b65186eb73c7650c3447163 Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 24 Jun 2019 11:43:01 +0100 Subject: [PATCH 12/12] clangformat Signed-off-by: David Shah --- common/timing.cc | 3 ++- gui/application.cc | 4 ++-- ice40/bitstream.cc | 5 +++-- ice40/cells.h | 5 ++++- ice40/pack.cc | 8 +++++--- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/common/timing.cc b/common/timing.cc index 997061e6..e67ac231 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -546,7 +546,8 @@ struct Timing for (size_t i = 0; i < sink_net->users.size(); i++) { auto &user = sink_net->users.at(i); if (user.cell == drv.cell && user.port == port.first) { - sink_nd.min_required.at(i) = std::min(sink_nd.min_required.at(i), net_min_required - comb_delay.maxDelay()); + sink_nd.min_required.at(i) = std::min(sink_nd.min_required.at(i), + net_min_required - comb_delay.maxDelay()); break; } } diff --git a/gui/application.cc b/gui/application.cc index d5f0f6a9..33a106bc 100644 --- a/gui/application.cc +++ b/gui/application.cc @@ -20,12 +20,12 @@ */ #include "application.h" -#include "log.h" -#include #include +#include #include #include #include +#include "log.h" NEXTPNR_NAMESPACE_BEGIN diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index d35c43aa..7632b443 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -611,10 +611,11 @@ void write_asc(const Context *ctx, std::ostream &out) set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_2", read_mode & 0x1); set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_3", read_mode & 0x2); } else if (cell.second->type == ctx->id("SB_LED_DRV_CUR")) { - set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "LED_DRV_CUR_EN", true, "IpConfig."); + set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "LED_DRV_CUR_EN", true, + "IpConfig."); } else if (cell.second->type == ctx->id("SB_RGB_DRV")) { const std::vector> rgb_params = { - {"RGB0_CURRENT", 6}, {"RGB1_CURRENT", 6}, {"RGB2_CURRENT", 6}}; + {"RGB0_CURRENT", 6}, {"RGB1_CURRENT", 6}, {"RGB2_CURRENT", 6}}; configure_extra_cell(config, ctx, cell.second.get(), rgb_params, true, std::string("IpConfig.")); set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "RGB_DRV_EN", true, "IpConfig."); } else if (cell.second->type == ctx->id("SB_RGBA_DRV")) { diff --git a/ice40/cells.h b/ice40/cells.h index 25a98573..3d9358da 100644 --- a/ice40/cells.h +++ b/ice40/cells.h @@ -78,7 +78,10 @@ inline bool is_sb_rgba_drv(const BaseCtx *ctx, const CellInfo *cell) { return ce inline bool is_sb_rgb_drv(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_RGB_DRV"); } -inline bool is_sb_led_drv_cur(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_LED_DRV_CUR"); } +inline bool is_sb_led_drv_cur(const BaseCtx *ctx, const CellInfo *cell) +{ + return cell->type == ctx->id("SB_LED_DRV_CUR"); +} inline bool is_sb_ledda_ip(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_LEDDA_IP"); } diff --git a/ice40/pack.cc b/ice40/pack.cc index 9a77048b..f520b295 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -450,7 +450,8 @@ static void pack_io(Context *ctx) } else if (ci->type == ctx->id("$nextpnr_obuf")) { NetInfo *net = ci->ports.at(ctx->id("I")).net; sb = net_only_drives(ctx, net, is_ice_iob, ctx->id("PACKAGE_PIN"), true, ci); - if (net && net->driver.cell && (is_sb_rgba_drv(ctx, net->driver.cell) || is_sb_rgb_drv(ctx, net->driver.cell))) + if (net && net->driver.cell && + (is_sb_rgba_drv(ctx, net->driver.cell) || is_sb_rgb_drv(ctx, net->driver.cell))) rgb = net->driver.cell; } if (sb != nullptr) { @@ -476,7 +477,8 @@ static void pack_io(Context *ctx) } } } else if (rgb != nullptr) { - log_info("%s use by SB_RGBA_DRV/SB_RGB_DRV %s, not creating SB_IO\n", ci->name.c_str(ctx), rgb->name.c_str(ctx)); + log_info("%s use by SB_RGBA_DRV/SB_RGB_DRV %s, not creating SB_IO\n", ci->name.c_str(ctx), + rgb->name.c_str(ctx)); disconnect_port(ctx, ci, ctx->id("I")); packed_cells.insert(ci->name); continue; @@ -1157,7 +1159,7 @@ static void pack_special(Context *ctx) } if (is_sb_rgb_drv(ctx, ci) && !ci->ledInfo.ledCurConnected) - log_error("Port RGBPU of SB_RGB_DRV should be driven by port LEDPU of SB_LED_DRV_CUR!\n"); + log_error("Port RGBPU of SB_RGB_DRV should be driven by port LEDPU of SB_LED_DRV_CUR!\n"); ci->ports.erase(ctx->id("RGBPU")); ci->ports.erase(ctx->id("RGB0"));