From c75a924c3f9dba4fd7d5c4e9674b29f7869a4e52 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 18 Jul 2018 12:12:05 +0200 Subject: ice40: Assign ArchArgs after packing Signed-off-by: David Shah --- ice40/arch.cc | 5 ++--- ice40/arch.h | 2 +- ice40/archdefs.h | 22 ++++++++++++++++++++-- ice40/bitstream.cc | 5 +++-- ice40/gfx.cc | 9 ++++----- ice40/gfx.h | 3 ++- ice40/pack.cc | 31 +++++++++++++++++++++++++++++++ 7 files changed, 63 insertions(+), 14 deletions(-) (limited to 'ice40') diff --git a/ice40/arch.cc b/ice40/arch.cc index 69848aff..1c6dd6a5 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -610,8 +610,7 @@ std::vector Arch::getDecalGraphics(DecalId decal) const } if (bel_type == TYPE_ICESTORM_RAM) { - for (int i = 0; i < 2; i++) - { + for (int i = 0; i < 2; i++) { int tx = chip_info->bel_data[bel.index].x; int ty = chip_info->bel_data[bel.index].y + i; @@ -621,7 +620,7 @@ std::vector Arch::getDecalGraphics(DecalId decal) const el.x1 = chip_info->bel_data[bel.index].x + logic_cell_x1; el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2; el.y1 = chip_info->bel_data[bel.index].y + logic_cell_y1; - el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 + 7*logic_cell_pitch; + el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 + 7 * logic_cell_pitch; el.z = 0; ret.push_back(el); diff --git a/ice40/arch.h b/ice40/arch.h index 5dab414b..1c47e958 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -584,7 +584,7 @@ struct Arch : BaseCtx range.e.cursor = chip_info->num_pips; return range; } - + IdString getPipName(PipId pip) const; uint32_t getPipChecksum(PipId pip) const { return pip.index; } diff --git a/ice40/archdefs.h b/ice40/archdefs.h index ce7d3f52..cf8a78f4 100644 --- a/ice40/archdefs.h +++ b/ice40/archdefs.h @@ -150,8 +150,26 @@ struct DecalId bool operator!=(const DecalId &other) const { return (type != other.type) || (index != other.index); } }; -struct ArchNetInfo { }; -struct ArchCellInfo { }; +struct ArchNetInfo +{ + bool is_global = false; +}; + +struct NetInfo; + +struct ArchCellInfo +{ + BelType belType = TYPE_NONE; + union + { + struct + { + bool dffEnable, negClk; + int inputCount; + const NetInfo *clk, *cen, *sr; + } lcInfo; + }; +}; NEXTPNR_NAMESPACE_END diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index a62c6c09..98a7a0e4 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -341,8 +341,9 @@ void write_asc(const Context *ctx, std::ostream &out) set_config(ti, config.at(y).at(x), "Cascade.IPCON_LC0" + std::to_string(lc_idx) + "_inmux02_5", true); else - set_config(ti, config.at(y).at(x), "Cascade.MULT" + std::to_string(int(tile - TILE_DSP0)) + - "_LC0" + std::to_string(lc_idx) + "_inmux02_5", + set_config(ti, config.at(y).at(x), + "Cascade.MULT" + std::to_string(int(tile - TILE_DSP0)) + "_LC0" + + std::to_string(lc_idx) + "_inmux02_5", true); } } diff --git a/ice40/gfx.cc b/ice40/gfx.cc index aa2fc9ce..f6ed789f 100644 --- a/ice40/gfx.cc +++ b/ice40/gfx.cc @@ -640,10 +640,8 @@ static bool getWireXY_local(GfxTileWireId id, float &x, float &y) return false; } -void pipGfx(std::vector &g, int x, int y, - float x1, float y1, float x2, float y2, - float swx1, float swy1, float swx2, float swy2, - GraphicElement::style_t style) +void pipGfx(std::vector &g, int x, int y, float x1, float y1, float x2, float y2, float swx1, + float swy1, float swx2, float swy2, GraphicElement::style_t style) { float tx = 0.5 * (x1 + x2); float ty = 0.5 * (y1 + y2); @@ -693,7 +691,8 @@ edge_pip: g.push_back(el); } -void gfxTilePip(std::vector &g, int x, int y, GfxTileWireId src, GfxTileWireId dst, GraphicElement::style_t style) +void gfxTilePip(std::vector &g, int x, int y, GfxTileWireId src, GfxTileWireId dst, + GraphicElement::style_t style) { float x1, y1, x2, y2; diff --git a/ice40/gfx.h b/ice40/gfx.h index a1cbd65b..8a55407d 100644 --- a/ice40/gfx.h +++ b/ice40/gfx.h @@ -468,7 +468,8 @@ enum GfxTileWireId }; void gfxTileWire(std::vector &g, int x, int y, GfxTileWireId id, GraphicElement::style_t style); -void gfxTilePip(std::vector &g, int x, int y, GfxTileWireId src, GfxTileWireId dst, GraphicElement::style_t style); +void gfxTilePip(std::vector &g, int x, int y, GfxTileWireId src, GfxTileWireId dst, + GraphicElement::style_t style); NEXTPNR_NAMESPACE_END diff --git a/ice40/pack.cc b/ice40/pack.cc index 76a52be0..e656e596 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -575,6 +575,36 @@ static void pack_special(Context *ctx) } } +// Assign arch arg info +static void assign_archargs(Context *ctx) +{ + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); + if (ctx->isGlobalNet(ni)) + ni->is_global = true; + } + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); + ci->belType = ctx->belTypeFromId(ci->type); + if (is_lc(ctx, ci)) { + ci->lcInfo.dffEnable = bool_or_default(ci->params, ctx->id("DFF_ENABLE")); + ci->lcInfo.negClk = bool_or_default(ci->params, ctx->id("NEG_CLK")); + ci->lcInfo.clk = get_net_or_empty(ci, ctx->id("CLK")); + ci->lcInfo.cen = get_net_or_empty(ci, ctx->id("CEN")); + ci->lcInfo.sr = get_net_or_empty(ci, ctx->id("SR")); + ci->lcInfo.inputCount = 0; + if (get_net_or_empty(ci, ctx->id("I0"))) + ci->lcInfo.inputCount++; + if (get_net_or_empty(ci, ctx->id("I1"))) + ci->lcInfo.inputCount++; + if (get_net_or_empty(ci, ctx->id("I2"))) + ci->lcInfo.inputCount++; + if (get_net_or_empty(ci, ctx->id("I3"))) + ci->lcInfo.inputCount++; + } + } +} + // Main pack function bool Arch::pack() { @@ -589,6 +619,7 @@ bool Arch::pack() pack_carries(ctx); pack_ram(ctx); pack_special(ctx); + assign_archargs(ctx); log_info("Checksum: 0x%08x\n", ctx->checksum()); return true; } catch (log_execution_error_exception) { -- cgit v1.2.3 From 70cfa7a6a4bbc796f1ddf23f53a932538eb3b84d Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 18 Jul 2018 12:21:02 +0200 Subject: ice40: Make assignArchArgs a Arch method; call also after legaliser Signed-off-by: David Shah --- ice40/arch.cc | 30 ++++++++++++++++++++++++++++++ ice40/arch.h | 5 +++++ ice40/pack.cc | 32 +------------------------------- ice40/place_legaliser.cc | 1 + 4 files changed, 37 insertions(+), 31 deletions(-) (limited to 'ice40') diff --git a/ice40/arch.cc b/ice40/arch.cc index 1c6dd6a5..a5c920bb 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -697,4 +697,34 @@ bool Arch::isGlobalNet(const NetInfo *net) const return net->driver.cell != nullptr && net->driver.port == id_glb_buf_out; } +// Assign arch arg info +void Arch::assignArchArgs() +{ + for (auto &net : getCtx()->nets) { + NetInfo *ni = net.second.get(); + if (isGlobalNet(ni)) + ni->is_global = true; + } + for (auto &cell : getCtx()->cells) { + CellInfo *ci = cell.second.get(); + ci->belType = belTypeFromId(ci->type); + if (ci->type == id_icestorm_lc) { + ci->lcInfo.dffEnable = bool_or_default(ci->params, id_dff_en); + ci->lcInfo.negClk = bool_or_default(ci->params, id_neg_clk); + ci->lcInfo.clk = get_net_or_empty(ci, id_clk); + ci->lcInfo.cen = get_net_or_empty(ci, id_cen); + ci->lcInfo.sr = get_net_or_empty(ci, id_sr); + ci->lcInfo.inputCount = 0; + if (get_net_or_empty(ci, id_i0)) + ci->lcInfo.inputCount++; + if (get_net_or_empty(ci, id_i1)) + ci->lcInfo.inputCount++; + if (get_net_or_empty(ci, id_i2)) + ci->lcInfo.inputCount++; + if (get_net_or_empty(ci, id_i3)) + ci->lcInfo.inputCount++; + } + } +} + NEXTPNR_NAMESPACE_END diff --git a/ice40/arch.h b/ice40/arch.h index 1c47e958..8821ded2 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -705,6 +705,11 @@ struct Arch : BaseCtx // Helper function for above bool logicCellsCompatible(const std::vector &cells) const; + // ------------------------------------------------- + // Assign architecure-specific arguments to nets and cells, which must be called between packing or further + // netlist modifications, and validity checks + void assignArchArgs(); + IdString id_glb_buf_out; IdString id_icestorm_lc, id_sb_io, id_sb_gb; IdString id_cen, id_clk, id_sr; diff --git a/ice40/pack.cc b/ice40/pack.cc index e656e596..6a6bdfaf 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -575,36 +575,6 @@ static void pack_special(Context *ctx) } } -// Assign arch arg info -static void assign_archargs(Context *ctx) -{ - for (auto &net : ctx->nets) { - NetInfo *ni = net.second.get(); - if (ctx->isGlobalNet(ni)) - ni->is_global = true; - } - for (auto &cell : ctx->cells) { - CellInfo *ci = cell.second.get(); - ci->belType = ctx->belTypeFromId(ci->type); - if (is_lc(ctx, ci)) { - ci->lcInfo.dffEnable = bool_or_default(ci->params, ctx->id("DFF_ENABLE")); - ci->lcInfo.negClk = bool_or_default(ci->params, ctx->id("NEG_CLK")); - ci->lcInfo.clk = get_net_or_empty(ci, ctx->id("CLK")); - ci->lcInfo.cen = get_net_or_empty(ci, ctx->id("CEN")); - ci->lcInfo.sr = get_net_or_empty(ci, ctx->id("SR")); - ci->lcInfo.inputCount = 0; - if (get_net_or_empty(ci, ctx->id("I0"))) - ci->lcInfo.inputCount++; - if (get_net_or_empty(ci, ctx->id("I1"))) - ci->lcInfo.inputCount++; - if (get_net_or_empty(ci, ctx->id("I2"))) - ci->lcInfo.inputCount++; - if (get_net_or_empty(ci, ctx->id("I3"))) - ci->lcInfo.inputCount++; - } - } -} - // Main pack function bool Arch::pack() { @@ -619,7 +589,7 @@ bool Arch::pack() pack_carries(ctx); pack_ram(ctx); pack_special(ctx); - assign_archargs(ctx); + ctx->assignArchArgs(); log_info("Checksum: 0x%08x\n", ctx->checksum()); return true; } catch (log_execution_error_exception) { diff --git a/ice40/place_legaliser.cc b/ice40/place_legaliser.cc index 5fffb4fb..ebcc0da7 100644 --- a/ice40/place_legaliser.cc +++ b/ice40/place_legaliser.cc @@ -127,6 +127,7 @@ class PlacementLegaliser legalise_others(); legalise_logic_tiles(); bool replaced_cells = replace_cells(); + ctx->assignArchArgs(); return legalised_carries && replaced_cells; } -- cgit v1.2.3 From d392b5f63587339c27a30c247f4a045f923edc4b Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 18 Jul 2018 12:51:07 +0200 Subject: ice40: Use xArchArgs in validity check Signed-off-by: David Shah --- ice40/arch.cc | 39 ++++++++++++++++++++++----------------- ice40/arch.h | 1 + ice40/arch_place.cc | 36 ++++++++++++++---------------------- ice40/place_legaliser.cc | 2 ++ 4 files changed, 39 insertions(+), 39 deletions(-) (limited to 'ice40') diff --git a/ice40/arch.cc b/ice40/arch.cc index a5c920bb..1825c142 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -707,23 +707,28 @@ void Arch::assignArchArgs() } for (auto &cell : getCtx()->cells) { CellInfo *ci = cell.second.get(); - ci->belType = belTypeFromId(ci->type); - if (ci->type == id_icestorm_lc) { - ci->lcInfo.dffEnable = bool_or_default(ci->params, id_dff_en); - ci->lcInfo.negClk = bool_or_default(ci->params, id_neg_clk); - ci->lcInfo.clk = get_net_or_empty(ci, id_clk); - ci->lcInfo.cen = get_net_or_empty(ci, id_cen); - ci->lcInfo.sr = get_net_or_empty(ci, id_sr); - ci->lcInfo.inputCount = 0; - if (get_net_or_empty(ci, id_i0)) - ci->lcInfo.inputCount++; - if (get_net_or_empty(ci, id_i1)) - ci->lcInfo.inputCount++; - if (get_net_or_empty(ci, id_i2)) - ci->lcInfo.inputCount++; - if (get_net_or_empty(ci, id_i3)) - ci->lcInfo.inputCount++; - } + assignCellArgs(ci); + } +} + +void Arch::assignCellArgs(CellInfo *cell) +{ + cell->belType = belTypeFromId(cell->type); + if (cell->type == id_icestorm_lc) { + cell->lcInfo.dffEnable = bool_or_default(cell->params, id_dff_en); + cell->lcInfo.negClk = bool_or_default(cell->params, id_neg_clk); + cell->lcInfo.clk = get_net_or_empty(cell, id_clk); + cell->lcInfo.cen = get_net_or_empty(cell, id_cen); + cell->lcInfo.sr = get_net_or_empty(cell, id_sr); + cell->lcInfo.inputCount = 0; + if (get_net_or_empty(cell, id_i0)) + cell->lcInfo.inputCount++; + if (get_net_or_empty(cell, id_i1)) + cell->lcInfo.inputCount++; + if (get_net_or_empty(cell, id_i2)) + cell->lcInfo.inputCount++; + if (get_net_or_empty(cell, id_i3)) + cell->lcInfo.inputCount++; } } diff --git a/ice40/arch.h b/ice40/arch.h index 8821ded2..8c1a3d41 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -709,6 +709,7 @@ struct Arch : BaseCtx // Assign architecure-specific arguments to nets and cells, which must be called between packing or further // netlist modifications, and validity checks void assignArchArgs(); + void assignCellArgs(CellInfo *cell); IdString id_glb_buf_out; IdString id_icestorm_lc, id_sb_io, id_sb_gb; diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc index dc1bc3eb..1f2943a0 100644 --- a/ice40/arch_place.cc +++ b/ice40/arch_place.cc @@ -31,45 +31,37 @@ bool Arch::logicCellsCompatible(const std::vector &cells) cons int locals_count = 0; for (auto cell : cells) { - if (bool_or_default(cell->params, id_dff_en)) { + NPNR_ASSERT(cell->belType == TYPE_ICESTORM_LC); + if (cell->lcInfo.dffEnable) { if (!dffs_exist) { dffs_exist = true; - cen = get_net_or_empty(cell, id_cen); - clk = get_net_or_empty(cell, id_clk); - sr = get_net_or_empty(cell, id_sr); + cen = cell->lcInfo.cen; + clk = cell->lcInfo.clk; + sr = cell->lcInfo.sr; - if (!isGlobalNet(cen) && cen != nullptr) + if (cen != nullptr && !cen->is_global) locals_count++; - if (!isGlobalNet(clk) && clk != nullptr) + if (clk != nullptr && !clk->is_global) locals_count++; - if (!isGlobalNet(sr) && sr != nullptr) + if (sr != nullptr && !sr->is_global) locals_count++; - if (bool_or_default(cell->params, id_neg_clk)) { + if (cell->lcInfo.negClk) { dffs_neg = true; } } else { - if (cen != get_net_or_empty(cell, id_cen)) + if (cen != cell->lcInfo.cen) return false; - if (clk != get_net_or_empty(cell, id_clk)) + if (clk != cell->lcInfo.clk) return false; - if (sr != get_net_or_empty(cell, id_sr)) + if (sr != cell->lcInfo.sr) return false; - if (dffs_neg != bool_or_default(cell->params, id_neg_clk)) + if (dffs_neg != cell->lcInfo.negClk) return false; } } - const NetInfo *i0 = get_net_or_empty(cell, id_i0), *i1 = get_net_or_empty(cell, id_i1), - *i2 = get_net_or_empty(cell, id_i2), *i3 = get_net_or_empty(cell, id_i3); - if (i0 != nullptr) - locals_count++; - if (i1 != nullptr) - locals_count++; - if (i2 != nullptr) - locals_count++; - if (i3 != nullptr) - locals_count++; + locals_count += cell->lcInfo.inputCount; } return locals_count <= 32; diff --git a/ice40/place_legaliser.cc b/ice40/place_legaliser.cc index ebcc0da7..3c82a1bd 100644 --- a/ice40/place_legaliser.cc +++ b/ice40/place_legaliser.cc @@ -372,6 +372,7 @@ class PlacementLegaliser NPNR_ASSERT(ctx->nets.find(co_i3_name) == ctx->nets.end()); ctx->nets[co_i3_name] = std::move(co_i3_net); IdString name = lc->name; + ctx->assignCellArgs(lc.get()); ctx->cells[lc->name] = std::move(lc); createdCells.insert(name); return ctx->cells[name].get(); @@ -416,6 +417,7 @@ class PlacementLegaliser ctx->nets[out_net_name] = std::move(out_net); IdString name = lc->name; + ctx->assignCellArgs(lc.get()); ctx->cells[lc->name] = std::move(lc); createdCells.insert(name); return ctx->cells[name].get(); -- cgit v1.2.3 From acdaec249ad9b6288cc053e4d504ca8f14e41ec6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 18 Jul 2018 13:46:00 +0200 Subject: Cleanups in iCE40 blinky and picorv32 tests Signed-off-by: Clifford Wolf --- ice40/blinky.ys | 2 +- ice40/picorv32.sh | 2 +- ice40/picorv32_arachne.sh | 9 --------- ice40/transform_arachne_loc.py | 24 ------------------------ 4 files changed, 2 insertions(+), 35 deletions(-) delete mode 100755 ice40/picorv32_arachne.sh delete mode 100755 ice40/transform_arachne_loc.py (limited to 'ice40') diff --git a/ice40/blinky.ys b/ice40/blinky.ys index bad0a8b4..a5dd2c85 100644 --- a/ice40/blinky.ys +++ b/ice40/blinky.ys @@ -1,3 +1,3 @@ read_verilog blinky.v -synth_ice40 -top blinky -nocarry +synth_ice40 -top blinky write_json blinky.json diff --git a/ice40/picorv32.sh b/ice40/picorv32.sh index 2c67f641..87426cde 100755 --- a/ice40/picorv32.sh +++ b/ice40/picorv32.sh @@ -2,5 +2,5 @@ set -ex rm -f picorv32.v wget https://raw.githubusercontent.com/cliffordwolf/picorv32/master/picorv32.v -yosys -p 'synth_ice40 -nocarry -json picorv32.json -top top' picorv32.v picorv32_top.v +yosys -p 'synth_ice40 -json picorv32.json -top top' picorv32.v picorv32_top.v ../nextpnr-ice40 --hx8k --asc picorv32.asc --json picorv32.json diff --git a/ice40/picorv32_arachne.sh b/ice40/picorv32_arachne.sh deleted file mode 100755 index b3960fdc..00000000 --- a/ice40/picorv32_arachne.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -ex -rm -f picorv32.v -wget https://raw.githubusercontent.com/cliffordwolf/picorv32/master/picorv32.v -yosys -p 'synth_ice40 -nocarry -blif picorv32.blif -top top' picorv32.v picorv32_top.v -arachne-pnr -d 8k --post-place-blif picorv32_place.blif picorv32.blif -o picorv32_arachne_all.asc -yosys -p "read_blif -wideports picorv32_place.blif; read_verilog -lib +/ice40/cells_sim.v; write_json picorv32_place.json" -./transform_arachne_loc.py picorv32_place.json > picorv32_place_nx.json -../nextpnr-ice40 --hx8k --asc picorv32_ar_placed.asc --json picorv32_place_nx.json --force diff --git a/ice40/transform_arachne_loc.py b/ice40/transform_arachne_loc.py deleted file mode 100755 index 14792845..00000000 --- a/ice40/transform_arachne_loc.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python3 -import json -import sys -import re - -with open(sys.argv[1]) as f: - data = json.load(f) - -for mod, moddata in data["modules"].items(): - if "cells" in moddata: - for cell, celldata in moddata["cells"].items(): - pos = re.split('[,/]', celldata["attributes"]["loc"]) - pos = [int(_) for _ in pos] - if celldata["type"] == "ICESTORM_LC": - celldata["attributes"]["BEL"] = "X%d/Y%d/lc%d" % (pos[0], pos[1], pos[2]) - elif celldata["type"] == "SB_IO": - celldata["attributes"]["BEL"] = "X%d/Y%d/io%d" % (pos[0], pos[1], pos[2]) - elif "RAM" in celldata["type"]: - celldata["attributes"]["BEL"] = "X%d/Y%d/ram" % (pos[0], pos[1]) - elif celldata["type"] == "SB_GB": - celldata["attributes"]["BEL"] = "X%d/Y%d/gb" % (pos[0], pos[1]) - else: - assert False -print(json.dumps(data, sort_keys=True, indent=4)) \ No newline at end of file -- cgit v1.2.3 From ddd94edfe0af32a33e5b71b9768c706f8b37d61b Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 18 Jul 2018 14:01:19 +0200 Subject: ice40: Fixes for inverted clocks Signed-off-by: David Shah --- ice40/bitstream.cc | 2 +- ice40/cells.cc | 3 ++- ice40/pack.cc | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'ice40') diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index 98a7a0e4..35a460f9 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -192,7 +192,7 @@ void write_asc(const Context *ctx, std::ostream &out) bool val = (pin_type >> i) & 0x01; set_config(ti, config.at(y).at(x), "IOB_" + std::to_string(z) + ".PINTYPE_" + std::to_string(i), val); } - + set_config(ti, config.at(y).at(x), "NegClk", neg_trigger); auto ieren = get_ieren(bi, x, y, z); int iex, iey, iez; std::tie(iex, iey, iez) = ieren; diff --git a/ice40/cells.cc b/ice40/cells.cc index 1ba40970..8e8679ee 100644 --- a/ice40/cells.cc +++ b/ice40/cells.cc @@ -256,7 +256,8 @@ bool is_clock_port(const BaseCtx *ctx, const PortRef &port) if (port.cell->type == ctx->id("ICESTORM_LC")) return port.port == ctx->id("CLK"); if (is_ram(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_RAM")) - return port.port == ctx->id("RCLK") || port.port == ctx->id("WCLK"); + return port.port == ctx->id("RCLK") || port.port == ctx->id("WCLK") || port.port == ctx->id("RCLKN") || + port.port == ctx->id("WCLKN"); return false; } diff --git a/ice40/pack.cc b/ice40/pack.cc index 6a6bdfaf..76e36151 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -277,6 +277,10 @@ static void pack_ram(Context *ctx) if (bpos != std::string::npos) { newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2); } + if (pi.name == ctx->id("RCLKN")) + newname = "RCLK"; + else if (pi.name == ctx->id("WCLKN")) + newname = "WCLK"; replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname)); } new_cells.push_back(std::move(packed)); -- cgit v1.2.3 From 08ceb8a059d96a0546c02eb3ee75e46093e2ee44 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 18 Jul 2018 14:34:32 +0200 Subject: ice40: Renaming Signed-off-by: David Shah --- ice40/arch.cc | 6 +++--- ice40/arch.h | 4 ++-- ice40/pack.cc | 2 +- ice40/place_legaliser.cc | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'ice40') diff --git a/ice40/arch.cc b/ice40/arch.cc index 1825c142..0decc513 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -698,7 +698,7 @@ bool Arch::isGlobalNet(const NetInfo *net) const } // Assign arch arg info -void Arch::assignArchArgs() +void Arch::assignArchInfo() { for (auto &net : getCtx()->nets) { NetInfo *ni = net.second.get(); @@ -707,11 +707,11 @@ void Arch::assignArchArgs() } for (auto &cell : getCtx()->cells) { CellInfo *ci = cell.second.get(); - assignCellArgs(ci); + assignCellInfo(ci); } } -void Arch::assignCellArgs(CellInfo *cell) +void Arch::assignCellInfo(CellInfo *cell) { cell->belType = belTypeFromId(cell->type); if (cell->type == id_icestorm_lc) { diff --git a/ice40/arch.h b/ice40/arch.h index 8c1a3d41..f0f734ce 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -708,8 +708,8 @@ struct Arch : BaseCtx // ------------------------------------------------- // Assign architecure-specific arguments to nets and cells, which must be called between packing or further // netlist modifications, and validity checks - void assignArchArgs(); - void assignCellArgs(CellInfo *cell); + void assignArchInfo(); + void assignCellInfo(CellInfo *cell); IdString id_glb_buf_out; IdString id_icestorm_lc, id_sb_io, id_sb_gb; diff --git a/ice40/pack.cc b/ice40/pack.cc index 76e36151..5f7e95f3 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -593,7 +593,7 @@ bool Arch::pack() pack_carries(ctx); pack_ram(ctx); pack_special(ctx); - ctx->assignArchArgs(); + ctx->assignArchInfo(); log_info("Checksum: 0x%08x\n", ctx->checksum()); return true; } catch (log_execution_error_exception) { diff --git a/ice40/place_legaliser.cc b/ice40/place_legaliser.cc index 3c82a1bd..2aefb839 100644 --- a/ice40/place_legaliser.cc +++ b/ice40/place_legaliser.cc @@ -127,7 +127,7 @@ class PlacementLegaliser legalise_others(); legalise_logic_tiles(); bool replaced_cells = replace_cells(); - ctx->assignArchArgs(); + ctx->assignArchInfo(); return legalised_carries && replaced_cells; } @@ -372,7 +372,7 @@ class PlacementLegaliser NPNR_ASSERT(ctx->nets.find(co_i3_name) == ctx->nets.end()); ctx->nets[co_i3_name] = std::move(co_i3_net); IdString name = lc->name; - ctx->assignCellArgs(lc.get()); + ctx->assignCellInfo(lc.get()); ctx->cells[lc->name] = std::move(lc); createdCells.insert(name); return ctx->cells[name].get(); @@ -417,7 +417,7 @@ class PlacementLegaliser ctx->nets[out_net_name] = std::move(out_net); IdString name = lc->name; - ctx->assignCellArgs(lc.get()); + ctx->assignCellInfo(lc.get()); ctx->cells[lc->name] = std::move(lc); createdCells.insert(name); return ctx->cells[name].get(); -- cgit v1.2.3 From b0d9b994eb211f4c4060f6b9802ea5692512e08c Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 19 Jul 2018 11:14:43 +0200 Subject: ice40: Adding data for extra cell configuration Signed-off-by: David Shah --- ice40/arch.h | 18 +++++++++++++++++- ice40/chipdb.py | 25 ++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 4 deletions(-) (limited to 'ice40') diff --git a/ice40/arch.h b/ice40/arch.h index f0f734ce..3b6d23dc 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -153,15 +153,31 @@ NPNR_PACKED_STRUCT(struct BitstreamInfoPOD { RelPtr ierens; }); +NPNR_PACKED_STRUCT(struct BelConfigEntryPOD { + RelPtr entry_name; + RelPtr cbit_name; + int8_t x, y; + int16_t padding; +}); + +// Stores mapping between bel parameters and config bits, +// for extra cells where this mapping is non-trivial +NPNR_PACKED_STRUCT(struct BelConfigPOD { + int32_t bel_index; + int32_t num_entries; + RelPtr entries; +}); + NPNR_PACKED_STRUCT(struct ChipInfoPOD { int32_t width, height; int32_t num_bels, num_wires, num_pips; - int32_t num_switches, num_packages; + int32_t num_switches, num_belcfgs, num_packages; RelPtr bel_data; RelPtr wire_data; RelPtr pip_data; RelPtr tile_grid; RelPtr bits_info; + RelPtr bel_config; RelPtr packages_data; }); diff --git a/ice40/chipdb.py b/ice40/chipdb.py index 698cd173..55ca1c1f 100644 --- a/ice40/chipdb.py +++ b/ice40/chipdb.py @@ -38,7 +38,7 @@ switches = list() ierens = list() extra_cells = dict() - +extra_cell_config = dict() packages = list() wire_uphill_belport = dict() @@ -567,6 +567,7 @@ def is_ec_output(ec_entry): def add_bel_ec(ec): ectype, x, y, z = ec bel = len(bel_name) + extra_cell_config[bel] = [] bel_name.append("X%d/Y%d/%s_%d" % (x, y, ectype.lower(), z)) bel_type.append(ectype) bel_pos.append((x, y, z)) @@ -578,8 +579,7 @@ def add_bel_ec(ec): else: add_bel_input(bel, wire_names[entry[1]], entry[0]) else: - # Configuration bit, need to create a structure for these - pass + extra_cell_config[bel].append(entry) for tile_xy, tile_type in sorted(tiles.items()): if tile_type == "logic": @@ -1175,6 +1175,23 @@ bba.l("tile_grid_%s" % dev_name, "TileType") for t in tilegrid: bba.u32(tiletypes[t], "tiletype") +for bel_idx, entries in sorted(extra_cell_config.items()): + if len(entries) > 0: + bba.l("bel%d_config_entries" % bel_idx, "BelConfigEntryPOD") + for entry in entries: + bba.s(entry[0], "entry_name") + bba.s(entry[1][2], "cbit_name") + bba.u8(entry[1][0], "x") + bba.u8(entry[1][1], "y") + bba.u16(0, "padding") + +if len(extra_cell_config) > 0: + bba.l("bel_config_%s" % dev_name, "BelConfigPOD") + for bel_idx, entries in sorted(extra_cell_config.items()): + bba.u32(bel_idx, "bel_index") + bba.u32(len(entries), "num_entries") + bba.r("bel%d_config_entries" % bel_idx if len(entries) > 0 else None, "entries") + bba.l("package_info_%s" % dev_name, "PackageInfoPOD") for info in packageinfo: bba.s(info[0], "name") @@ -1188,12 +1205,14 @@ bba.u32(len(bel_name), "num_bels") bba.u32(num_wires, "num_wires") bba.u32(len(pipinfo), "num_pips") bba.u32(len(switchinfo), "num_switches") +bba.u32(len(extra_cell_config), "num_belcfgs") bba.u32(len(packageinfo), "num_packages") bba.r("bel_data_%s" % dev_name, "bel_data") bba.r("wire_data_%s" % dev_name, "wire_data") bba.r("pip_data_%s" % dev_name, "pip_data") bba.r("tile_grid_%s" % dev_name, "tile_grid") bba.r("bits_info_%s" % dev_name, "bits_info") +bba.r("bel_config_%s" % dev_name if len(extra_cell_config) > 0 else None, "bel_config") bba.r("package_info_%s" % dev_name, "packages_data") bba.finalize() -- cgit v1.2.3 From d221e90706915c8ba540805167c8e9e07d4c3d6f Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 19 Jul 2018 11:43:10 +0200 Subject: Reducing performance cost of asserts Signed-off-by: David Shah --- ice40/bitstream.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ice40') diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index 35a460f9..09312b07 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -36,7 +36,7 @@ const ConfigEntryPOD &find_config(const TileInfoPOD &tile, const std::string &na return tile.entries[i]; } } - NPNR_ASSERT_FALSE("unable to find config bit " + name); + NPNR_ASSERT_FALSE_STR("unable to find config bit " + name); } std::tuple get_ieren(const BitstreamInfoPOD &bi, int8_t x, int8_t y, int8_t z) -- cgit v1.2.3 From 0cb9ec0757c635982e0bd64f3e314786762c7483 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 19 Jul 2018 12:04:35 +0200 Subject: ice40: Add virtual padin wires for intoscs and GB_IOs Signed-off-by: David Shah --- ice40/chipdb.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'ice40') diff --git a/ice40/chipdb.py b/ice40/chipdb.py index 55ca1c1f..329fef56 100644 --- a/ice40/chipdb.py +++ b/ice40/chipdb.py @@ -159,7 +159,7 @@ def wire_type(name): name = name.split('/')[-1] wt = None - if name.startswith("glb_netwk_"): + if name.startswith("glb_netwk_") or name.startswith("padin_"): wt = "GLOBAL" elif name.startswith("D_IN_") or name.startswith("D_OUT_"): wt = "LOCAL" @@ -432,6 +432,19 @@ with open(args.filename, "r") as f: extra_cells[mode[1]].append((line[0], (int(line[1]), int(line[2]), line[3]))) continue +def add_wire(x, y, name): + global num_wires + wire_idx = num_wires + num_wires = num_wires + 1 + wname = (x, y, name) + wire_names[wname] = wire_idx + wire_names_r[wire_idx] = wname + wire_segments[wire_idx] = dict() + +# Add virtual padin wires +for i in range(8): + add_wire(0, 0, "padin_%d" % i) + def add_bel_input(bel, wire, port): if wire not in wire_downhill_belports: wire_downhill_belports[wire] = set() -- cgit v1.2.3 From 6c38df7295747ddd37a751ea5de2a73e95a021d1 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 19 Jul 2018 13:22:46 +0200 Subject: ice40: Adding cell definition for DSPs Signed-off-by: David Shah --- ice40/arch.cc | 8 +++---- ice40/archdefs.h | 2 +- ice40/cells.cc | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ice40/cells.h | 2 ++ 4 files changed, 79 insertions(+), 5 deletions(-) (limited to 'ice40') diff --git a/ice40/arch.cc b/ice40/arch.cc index 0decc513..1aa02294 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -44,8 +44,8 @@ IdString Arch::belTypeToId(BelType type) const return id("ICESTORM_PLL"); if (type == TYPE_SB_WARMBOOT) return id("SB_WARMBOOT"); - if (type == TYPE_SB_MAC16) - return id("SB_MAC16"); + if (type == TYPE_ICESTORM_DSP) + return id("ICESTORM_DSP"); if (type == TYPE_ICESTORM_HFOSC) return id("ICESTORM_HFOSC"); if (type == TYPE_ICESTORM_LFOSC) @@ -79,8 +79,8 @@ BelType Arch::belTypeFromId(IdString type) const return TYPE_ICESTORM_PLL; if (type == id("SB_WARMBOOT")) return TYPE_SB_WARMBOOT; - if (type == id("SB_MAC16")) - return TYPE_SB_MAC16; + if (type == id("ICESTORM_DSP")) + return TYPE_ICESTORM_DSP; if (type == id("ICESTORM_HFOSC")) return TYPE_ICESTORM_HFOSC; if (type == id("ICESTORM_LFOSC")) diff --git a/ice40/archdefs.h b/ice40/archdefs.h index cf8a78f4..55e2c2fb 100644 --- a/ice40/archdefs.h +++ b/ice40/archdefs.h @@ -54,7 +54,7 @@ enum BelType : int32_t TYPE_SB_GB, TYPE_ICESTORM_PLL, TYPE_SB_WARMBOOT, - TYPE_SB_MAC16, + TYPE_ICESTORM_DSP, TYPE_ICESTORM_HFOSC, TYPE_ICESTORM_LFOSC, TYPE_SB_I2C, diff --git a/ice40/cells.cc b/ice40/cells.cc index 8e8679ee..f07e0d22 100644 --- a/ice40/cells.cc +++ b/ice40/cells.cc @@ -142,6 +142,71 @@ std::unique_ptr create_ice_cell(Context *ctx, IdString type, std::stri for (int i = 0; i < 4; i++) { add_port(ctx, new_cell.get(), "MASKWREN_" + std::to_string(i), PORT_IN); } + } else if (type == ctx->id("ICESTORM_DSP")) { + new_cell->params[ctx->id("NEG_TRIGGER")] = "0"; + + new_cell->params[ctx->id("C_REG")] = "0"; + new_cell->params[ctx->id("A_REG")] = "0"; + new_cell->params[ctx->id("B_REG")] = "0"; + new_cell->params[ctx->id("D_REG")] = "0"; + new_cell->params[ctx->id("TOP_8x8_MULT_REG")] = "0"; + new_cell->params[ctx->id("BOT_8x8_MULT_REG")] = "0"; + new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG1")] = "0"; + new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG2")] = "0"; + + new_cell->params[ctx->id("TOPOUTPUT_SELECT")] = "0"; + new_cell->params[ctx->id("TOPADDSUB_LOWERINPUT")] = "0"; + new_cell->params[ctx->id("TOPADDSUB_UPPERINPUT")] = "0"; + new_cell->params[ctx->id("TOPADDSUB_CARRYSELECT")] = "0"; + + new_cell->params[ctx->id("BOTOUTPUT_SELECT")] = "0"; + new_cell->params[ctx->id("BOTADDSUB_LOWERINPUT")] = "0"; + new_cell->params[ctx->id("BOTADDSUB_UPPERINPUT")] = "0"; + new_cell->params[ctx->id("BOTADDSUB_CARRYSELECT")] = "0"; + + new_cell->params[ctx->id("MODE_8x8")] = "0"; + new_cell->params[ctx->id("A_SIGNED")] = "0"; + new_cell->params[ctx->id("B_SIGNED")] = "0"; + + add_port(ctx, new_cell.get(), "CLK", PORT_IN); + add_port(ctx, new_cell.get(), "CE", PORT_IN); + for (int i = 0; i < 16; i++) { + add_port(ctx, new_cell.get(), "C_" + std::to_string(i), PORT_IN); + add_port(ctx, new_cell.get(), "A_" + std::to_string(i), PORT_IN); + add_port(ctx, new_cell.get(), "B_" + std::to_string(i), PORT_IN); + add_port(ctx, new_cell.get(), "D_" + std::to_string(i), PORT_IN); + } + add_port(ctx, new_cell.get(), "AHOLD", PORT_IN); + add_port(ctx, new_cell.get(), "BHOLD", PORT_IN); + add_port(ctx, new_cell.get(), "CHOLD", PORT_IN); + add_port(ctx, new_cell.get(), "DHOLD", PORT_IN); + + add_port(ctx, new_cell.get(), "IRSTTOP", PORT_IN); + add_port(ctx, new_cell.get(), "IRSTBOT", PORT_IN); + add_port(ctx, new_cell.get(), "ORSTTOP", PORT_IN); + add_port(ctx, new_cell.get(), "ORSTBOT", PORT_IN); + + add_port(ctx, new_cell.get(), "OLOADTOP", PORT_IN); + add_port(ctx, new_cell.get(), "OLOADBOT", PORT_IN); + + add_port(ctx, new_cell.get(), "ADDSUBTOP", PORT_IN); + add_port(ctx, new_cell.get(), "ADDSUBBOT", PORT_IN); + + add_port(ctx, new_cell.get(), "OHOLDTOP", PORT_IN); + add_port(ctx, new_cell.get(), "OHOLDBOT", PORT_IN); + + add_port(ctx, new_cell.get(), "CI", PORT_IN); + add_port(ctx, new_cell.get(), "ACCUMCI", PORT_IN); + add_port(ctx, new_cell.get(), "SIGNEXTIN", PORT_IN); + + for (int i = 0; i < 32; i++) { + add_port(ctx, new_cell.get(), "O_" + std::to_string(i), PORT_OUT); + } + + add_port(ctx, new_cell.get(), "CO", PORT_OUT); + add_port(ctx, new_cell.get(), "ACCUMCO", PORT_OUT); + add_port(ctx, new_cell.get(), "SIGNEXTOUT", PORT_OUT); + } else { log_error("unable to create iCE40 cell of type %s", type.c_str(ctx)); } @@ -258,6 +323,8 @@ bool is_clock_port(const BaseCtx *ctx, const PortRef &port) if (is_ram(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_RAM")) return port.port == ctx->id("RCLK") || port.port == ctx->id("WCLK") || port.port == ctx->id("RCLKN") || port.port == ctx->id("WCLKN"); + if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP")) + return port.port == ctx->id("CLK"); return false; } @@ -269,6 +336,9 @@ bool is_reset_port(const BaseCtx *ctx, const PortRef &port) return port.port == ctx->id("R") || port.port == ctx->id("S"); if (port.cell->type == ctx->id("ICESTORM_LC")) return port.port == ctx->id("SR"); + if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP")) + return port.port == ctx->id("IRSTTOP") || port.port == ctx->id("IRSTBOT") || port.port == ctx->id("ORSTTOP") || + port.port == ctx->id("ORSTBOT"); return false; } @@ -280,6 +350,8 @@ bool is_enable_port(const BaseCtx *ctx, const PortRef &port) return port.port == ctx->id("E"); if (port.cell->type == ctx->id("ICESTORM_LC")) return port.port == ctx->id("CEN"); + if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP")) + return port.port == ctx->id("CE"); return false; } diff --git a/ice40/cells.h b/ice40/cells.h index 9f99835d..2f9c77e8 100644 --- a/ice40/cells.h +++ b/ice40/cells.h @@ -69,6 +69,8 @@ inline bool is_sb_hfosc(const BaseCtx *ctx, const CellInfo *cell) { return cell- inline bool is_sb_spram(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_SPRAM256KA"); } +inline bool is_sb_mac16(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_MAC16"); } + // Convert a SB_LUT primitive to (part of) an ICESTORM_LC, swapping ports // as needed. Set no_dff if a DFF is not being used, so that the output // can be reconnected -- cgit v1.2.3 From bff7d673eda60f1ff8a59fd49a9e57a9ba8fa393 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 19 Jul 2018 14:03:48 +0200 Subject: ice40: Packer and bitstream gen support for MAC16s Signed-off-by: David Shah --- ice40/bitstream.cc | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++- ice40/cells.cc | 5 +-- ice40/pack.cc | 19 ++++++++++++ 3 files changed, 111 insertions(+), 3 deletions(-) (limited to 'ice40') diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index 09312b07..c12fa90e 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -90,12 +90,79 @@ std::string get_param_str_or_def(const CellInfo *cell, const IdString param, std char get_hexdigit(int i) { return std::string("0123456789ABCDEF").at(i); } +static const BelConfigPOD &get_ec_config(const ChipInfoPOD *chip, BelId bel) +{ + for (int i = 0; i < chip->num_belcfgs; i++) { + if (chip->bel_config[i].bel_index == bel.index) + return chip->bel_config[i]; + } + NPNR_ASSERT_FALSE("failed to find bel config"); +} + +typedef std::vector>>> chipconfig_t; + +static void set_ec_cbit(chipconfig_t &config, const Context *ctx, const BelConfigPOD &cell_cbits, std::string name, + bool value) +{ + const ChipInfoPOD *chip = ctx->chip_info; + + for (int i = 0; i < cell_cbits.num_entries; i++) { + const auto &cbit = cell_cbits.entries[i]; + if (cbit.entry_name.get() == name) { + const auto &ti = chip->bits_info->tiles_nonrouting[tile_at(ctx, cbit.x, cbit.y)]; + set_config(ti, config.at(cbit.y).at(cbit.x), std::string("IpConfig.") + cbit.cbit_name.get(), value); + return; + } + } + NPNR_ASSERT_FALSE_STR("failed to config extra cell config bit " + name); +} + +void configure_extra_cell(chipconfig_t &config, const Context *ctx, CellInfo *cell, + const std::vector> ¶ms, bool string_style) +{ + const ChipInfoPOD *chip = ctx->chip_info; + const auto &bc = get_ec_config(chip, cell->bel); + for (auto p : params) { + std::vector value; + if (string_style) { + // Lattice's weird string style params, not sure if + // prefixes other than 0b should be supported, only 0b features in docs + std::string raw = get_param_str_or_def(cell, ctx->id(p.first), "0b0"); + assert(raw.substr(0, 2) == "0b"); + raw = raw.substr(2); + value.resize(raw.length()); + for (int i = 0; i < (int)raw.length(); i++) { + if (raw[i] == '1') { + value[(raw.length() - 1) - i] = 1; + } else { + assert(raw[i] == '0'); + value[(raw.length() - 1) - i] = 0; + } + } + } else { + int ival = get_param_or_def(cell, ctx->id(p.first), 0); + + for (int i = 0; i < p.second; i++) + value.push_back((ival >> i) & 0x1); + } + + value.resize(p.second); + if (p.second == 1) { + set_ec_cbit(config, ctx, bc, p.first, value.at(0)); + } else { + for (int i = 0; i < p.second; i++) { + set_ec_cbit(config, ctx, bc, p.first + "_" + std::to_string(i), value.at(i)); + } + } + } +} + void write_asc(const Context *ctx, std::ostream &out) { // [y][x][row][col] const ChipInfoPOD &ci = *ctx->chip_info; const BitstreamInfoPOD &bi = *ci.bits_info; - std::vector>>> config; + chipconfig_t config; config.resize(ci.height); for (int y = 0; y < ci.height; y++) { config.at(y).resize(ci.width); @@ -265,6 +332,27 @@ void write_asc(const Context *ctx, std::ostream &out) NPNR_ASSERT(false); } } + } else if (cell.second->type == ctx->id("ICESTORM_DSP")) { + const std::vector> mac16_params = {{"C_REG", 1}, + {"A_REG", 1}, + {"B_REG", 1}, + {"D_REG", 1}, + {"TOP_8x8_MULT_REG", 1}, + {"BOT_8x8_MULT_REG", 1}, + {"PIPELINE_16x16_MULT_REG1", 1}, + {"PIPELINE_16x16_MULT_REG2", 1}, + {"TOPOUTPUT_SELECT", 2}, + {"TOPADDSUB_LOWERINPUT", 2}, + {"TOPADDSUB_UPPERINPUT", 1}, + {"TOPADDSUB_CARRYSELECT", 2}, + {"BOTOUTPUT_SELECT", 2}, + {"BOTADDSUB_LOWERINPUT", 2}, + {"BOTADDSUB_UPPERINPUT", 1}, + {"BOTADDSUB_CARRYSELECT", 2}, + {"MODE_8x8", 1}, + {"A_SIGNED", 1}, + {"B_SIGNED", 1}}; + configure_extra_cell(config, ctx, cell.second.get(), mac16_params, false); } else { NPNR_ASSERT(false); } diff --git a/ice40/cells.cc b/ice40/cells.cc index f07e0d22..71a65d44 100644 --- a/ice40/cells.cc +++ b/ice40/cells.cc @@ -350,8 +350,9 @@ bool is_enable_port(const BaseCtx *ctx, const PortRef &port) return port.port == ctx->id("E"); if (port.cell->type == ctx->id("ICESTORM_LC")) return port.port == ctx->id("CEN"); - if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP")) - return port.port == ctx->id("CE"); + // FIXME + // if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP")) + // return port.port == ctx->id("CE"); return false; } diff --git a/ice40/pack.cc b/ice40/pack.cc index 5f7e95f3..78df00f6 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -568,6 +568,25 @@ 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_mac16(ctx, ci)) { + std::unique_ptr packed = + create_ice_cell(ctx, ctx->id("ICESTORM_DSP"), ci->name.str(ctx) + "_DSP"); + packed_cells.insert(ci->name); + for (auto attr : ci->attrs) + packed->attrs[attr.first] = attr.second; + for (auto param : ci->params) + packed->params[param.first] = param.second; + + for (auto port : ci->ports) { + PortInfo &pi = port.second; + std::string newname = pi.name.str(ctx); + size_t bpos = newname.find('['); + if (bpos != std::string::npos) { + newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2); + } + replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname)); + } + new_cells.push_back(std::move(packed)); } } -- cgit v1.2.3 From 79dc910b40b082c9d74d010557b7939fb18535fe Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 19 Jul 2018 14:32:30 +0200 Subject: ice40: Trim DSP inputs that are constant where appropriate Signed-off-by: David Shah --- ice40/pack.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'ice40') diff --git a/ice40/pack.cc b/ice40/pack.cc index 78df00f6..7e2e389c 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -307,6 +307,10 @@ static void set_net_constant(const Context *ctx, NetInfo *orig, NetInfo *constne if ((is_lut(ctx, uc) || is_lc(ctx, uc) || is_carry(ctx, uc)) && (user.port.str(ctx).at(0) == 'I') && !constval) { uc->ports[user.port].net = nullptr; + } else if ((is_sb_mac16(ctx, uc) || uc->type == ctx->id("ICESTORM_DSP")) && + (user.port != ctx->id("CLK") && + ((constval && user.port == ctx->id("CE")) || (!constval && user.port != ctx->id("CE"))))) { + uc->ports[user.port].net = nullptr; } else { uc->ports[user.port].net = constnet; constnet->users.push_back(user); -- cgit v1.2.3