aboutsummaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
Diffstat (limited to 'generic')
-rw-r--r--generic/arch.cc102
-rw-r--r--generic/arch.h5
-rw-r--r--generic/arch_pybindings.cc2
-rw-r--r--generic/cells.cc14
-rw-r--r--generic/examples/.gitignore3
-rw-r--r--generic/examples/bitstream.py2
-rw-r--r--generic/examples/blinky.v13
-rw-r--r--generic/examples/blinky_tb.v38
-rw-r--r--generic/examples/simple.py7
-rwxr-xr-xgeneric/examples/simple.sh3
-rw-r--r--generic/examples/simple_timing.py26
-rwxr-xr-xgeneric/examples/simtest.sh7
-rw-r--r--generic/main.cc6
-rw-r--r--generic/pack.cc17
-rw-r--r--generic/synth/cells_map.v4
-rw-r--r--generic/synth/prims.v28
16 files changed, 210 insertions, 67 deletions
diff --git a/generic/arch.cc b/generic/arch.cc
index 9e59540e..c1c01d26 100644
--- a/generic/arch.cc
+++ b/generic/arch.cc
@@ -21,11 +21,36 @@
#include <math.h>
#include "nextpnr.h"
#include "placer1.h"
+#include "placer_heap.h"
#include "router1.h"
#include "util.h"
NEXTPNR_NAMESPACE_BEGIN
+WireInfo &Arch::wire_info(IdString wire)
+{
+ auto w = wires.find(wire);
+ if (w == wires.end())
+ NPNR_ASSERT_FALSE_STR("no wire named " + wire.str(this));
+ return w->second;
+}
+
+PipInfo &Arch::pip_info(IdString pip)
+{
+ auto p = pips.find(pip);
+ if (p == pips.end())
+ NPNR_ASSERT_FALSE_STR("no pip named " + pip.str(this));
+ return p->second;
+}
+
+BelInfo &Arch::bel_info(IdString bel)
+{
+ auto b = bels.find(bel);
+ if (b == bels.end())
+ NPNR_ASSERT_FALSE_STR("no bel named " + bel.str(this));
+ return b->second;
+}
+
void Arch::addWire(IdString name, IdString type, int x, int y)
{
NPNR_ASSERT(wires.count(name) == 0);
@@ -49,8 +74,8 @@ void Arch::addPip(IdString name, IdString type, IdString srcWire, IdString dstWi
pi.delay = delay;
pi.loc = loc;
- wires.at(srcWire).downhill.push_back(name);
- wires.at(dstWire).uphill.push_back(name);
+ wire_info(srcWire).downhill.push_back(name);
+ wire_info(dstWire).uphill.push_back(name);
pip_ids.push_back(name);
if (int(tilePipDimZ.size()) <= loc.x)
@@ -74,7 +99,7 @@ void Arch::addAlias(IdString name, IdString type, IdString srcWire, IdString dst
pi.dstWire = dstWire;
pi.delay = delay;
- wires.at(srcWire).aliases.push_back(name);
+ wire_info(srcWire).aliases.push_back(name);
pip_ids.push_back(name);
}
@@ -114,38 +139,38 @@ void Arch::addBel(IdString name, IdString type, Loc loc, bool gb)
void Arch::addBelInput(IdString bel, IdString name, IdString wire)
{
- NPNR_ASSERT(bels.at(bel).pins.count(name) == 0);
- PinInfo &pi = bels.at(bel).pins[name];
+ NPNR_ASSERT(bel_info(bel).pins.count(name) == 0);
+ PinInfo &pi = bel_info(bel).pins[name];
pi.name = name;
pi.wire = wire;
pi.type = PORT_IN;
- wires.at(wire).downhill_bel_pins.push_back(BelPin{bel, name});
- wires.at(wire).bel_pins.push_back(BelPin{bel, name});
+ wire_info(wire).downhill_bel_pins.push_back(BelPin{bel, name});
+ wire_info(wire).bel_pins.push_back(BelPin{bel, name});
}
void Arch::addBelOutput(IdString bel, IdString name, IdString wire)
{
- NPNR_ASSERT(bels.at(bel).pins.count(name) == 0);
- PinInfo &pi = bels.at(bel).pins[name];
+ NPNR_ASSERT(bel_info(bel).pins.count(name) == 0);
+ PinInfo &pi = bel_info(bel).pins[name];
pi.name = name;
pi.wire = wire;
pi.type = PORT_OUT;
- wires.at(wire).uphill_bel_pin = BelPin{bel, name};
- wires.at(wire).bel_pins.push_back(BelPin{bel, name});
+ wire_info(wire).uphill_bel_pin = BelPin{bel, name};
+ wire_info(wire).bel_pins.push_back(BelPin{bel, name});
}
void Arch::addBelInout(IdString bel, IdString name, IdString wire)
{
- NPNR_ASSERT(bels.at(bel).pins.count(name) == 0);
- PinInfo &pi = bels.at(bel).pins[name];
+ NPNR_ASSERT(bel_info(bel).pins.count(name) == 0);
+ PinInfo &pi = bel_info(bel).pins[name];
pi.name = name;
pi.wire = wire;
pi.type = PORT_INOUT;
- wires.at(wire).downhill_bel_pins.push_back(BelPin{bel, name});
- wires.at(wire).bel_pins.push_back(BelPin{bel, name});
+ wire_info(wire).downhill_bel_pins.push_back(BelPin{bel, name});
+ wire_info(wire).bel_pins.push_back(BelPin{bel, name});
}
void Arch::addGroupBel(IdString group, IdString bel) { groups[group].bels.push_back(bel); }
@@ -164,19 +189,19 @@ void Arch::addDecalGraphic(DecalId decal, const GraphicElement &graphic)
void Arch::setWireDecal(WireId wire, DecalXY decalxy)
{
- wires.at(wire).decalxy = decalxy;
+ wire_info(wire).decalxy = decalxy;
refreshUiWire(wire);
}
void Arch::setPipDecal(PipId pip, DecalXY decalxy)
{
- pips.at(pip).decalxy = decalxy;
+ pip_info(pip).decalxy = decalxy;
refreshUiPip(pip);
}
void Arch::setBelDecal(BelId bel, DecalXY decalxy)
{
- bels.at(bel).decalxy = decalxy;
+ bel_info(bel).decalxy = decalxy;
refreshUiBel(bel);
}
@@ -186,11 +211,11 @@ void Arch::setGroupDecal(GroupId group, DecalXY decalxy)
refreshUiGroup(group);
}
-void Arch::setWireAttr(IdString wire, IdString key, const std::string &value) { wires.at(wire).attrs[key] = value; }
+void Arch::setWireAttr(IdString wire, IdString key, const std::string &value) { wire_info(wire).attrs[key] = value; }
-void Arch::setPipAttr(IdString pip, IdString key, const std::string &value) { pips.at(pip).attrs[key] = value; }
+void Arch::setPipAttr(IdString pip, IdString key, const std::string &value) { pip_info(pip).attrs[key] = value; }
-void Arch::setBelAttr(IdString bel, IdString key, const std::string &value) { bels.at(bel).attrs[key] = value; }
+void Arch::setBelAttr(IdString bel, IdString key, const std::string &value) { bel_info(bel).attrs[key] = value; }
void Arch::setLutK(int K) { args.K = K; }
@@ -494,8 +519,29 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay
bool Arch::place()
{
std::string placer = str_or_default(settings, id("placer"), defaultPlacer);
- // FIXME: No HeAP because it needs a list of IO buffers
- if (placer == "sa") {
+ if (placer == "heap") {
+ bool have_iobuf_or_constr = false;
+ for (auto cell : sorted(cells)) {
+ CellInfo *ci = cell.second;
+ if (ci->type == id("GENERIC_IOB") || ci->bel != BelId() || ci->attrs.count(id("BEL"))) {
+ have_iobuf_or_constr = true;
+ break;
+ }
+ }
+ bool retVal;
+ if (!have_iobuf_or_constr) {
+ log_warning("Unable to use HeAP due to a lack of IO buffers or constrained cells as anchors; reverting to "
+ "SA.\n");
+ retVal = placer1(getCtx(), Placer1Cfg(getCtx()));
+ } else {
+ PlacerHeapCfg cfg(getCtx());
+ cfg.ioBufTypes.insert(id("GENERIC_IOB"));
+ retVal = placer_heap(getCtx(), cfg);
+ }
+ getCtx()->settings[getCtx()->id("place")] = 1;
+ archInfoToAttributes();
+ return retVal;
+ } else if (placer == "sa") {
bool retVal = placer1(getCtx(), Placer1Cfg(getCtx()));
getCtx()->settings[getCtx()->id("place")] = 1;
archInfoToAttributes();
@@ -596,9 +642,17 @@ bool Arch::isBelLocationValid(BelId bel) const
return cellsCompatible(cells.data(), int(cells.size()));
}
+#ifdef WITH_HEAP
+const std::string Arch::defaultPlacer = "heap";
+#else
const std::string Arch::defaultPlacer = "sa";
-const std::vector<std::string> Arch::availablePlacers = {"sa"};
+#endif
+const std::vector<std::string> Arch::availablePlacers = {"sa",
+#ifdef WITH_HEAP
+ "heap"
+#endif
+};
void Arch::assignArchInfo()
{
for (auto &cell : getCtx()->cells) {
diff --git a/generic/arch.h b/generic/arch.h
index e9d3593c..444d2636 100644
--- a/generic/arch.h
+++ b/generic/arch.h
@@ -122,6 +122,11 @@ struct Arch : BaseCtx
std::unordered_map<IdString, BelInfo> bels;
std::unordered_map<GroupId, GroupInfo> groups;
+ // These functions include useful errors if not found
+ WireInfo &wire_info(IdString wire);
+ PipInfo &pip_info(IdString wire);
+ BelInfo &bel_info(IdString wire);
+
std::vector<IdString> bel_ids, wire_ids, pip_ids;
std::unordered_map<Loc, BelId> bel_by_loc;
diff --git a/generic/arch_pybindings.cc b/generic/arch_pybindings.cc
index 8526e409..2600cac0 100644
--- a/generic/arch_pybindings.cc
+++ b/generic/arch_pybindings.cc
@@ -141,6 +141,7 @@ void arch_wrap_python()
typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap;
typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap;
+ typedef std::unordered_map<IdString, HierarchicalCell> HierarchyMap;
readonly_wrapper<Context, decltype(&Context::cells), &Context::cells, wrap_context<CellMap &>>::def_wrap(ctx_cls,
"cells");
@@ -231,6 +232,7 @@ void arch_wrap_python()
WRAP_MAP_UPTR(CellMap, "IdCellMap");
WRAP_MAP_UPTR(NetMap, "IdNetMap");
+ WRAP_MAP(HierarchyMap, wrap_context<HierarchicalCell &>, "HierarchyMap");
WRAP_VECTOR(const std::vector<IdString>, conv_to_str<IdString>);
}
diff --git a/generic/cells.cc b/generic/cells.cc
index 53886e33..c4421f90 100644
--- a/generic/cells.cc
+++ b/generic/cells.cc
@@ -42,7 +42,7 @@ std::unique_ptr<CellInfo> create_generic_cell(Context *ctx, IdString type, std::
}
new_cell->type = type;
if (type == ctx->id("GENERIC_SLICE")) {
- new_cell->params[ctx->id("K")] = std::to_string(ctx->args.K);
+ new_cell->params[ctx->id("K")] = ctx->args.K;
new_cell->params[ctx->id("INIT")] = 0;
new_cell->params[ctx->id("FF_USED")] = 0;
@@ -51,6 +51,7 @@ std::unique_ptr<CellInfo> create_generic_cell(Context *ctx, IdString type, std::
add_port(ctx, new_cell.get(), "CLK", PORT_IN);
+ add_port(ctx, new_cell.get(), "F", PORT_OUT);
add_port(ctx, new_cell.get(), "Q", PORT_OUT);
} else if (type == ctx->id("GENERIC_IOB")) {
new_cell->params[ctx->id("INPUT_USED")] = 0;
@@ -80,8 +81,8 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)
}
if (no_dff) {
- replace_port(lut, ctx->id("Q"), lc, ctx->id("Q"));
lc->params[ctx->id("FF_USED")] = 0;
+ replace_port(lut, ctx->id("Q"), lc, ctx->id("F"));
}
}
@@ -91,7 +92,14 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l
replace_port(dff, ctx->id("CLK"), lc, ctx->id("CLK"));
if (pass_thru_lut) {
- lc->params[ctx->id("INIT")] = 2;
+ // Fill LUT with alternating 10
+ const int init_size = 1 << lc->params[ctx->id("K")].as_int64();
+ std::string init;
+ init.reserve(init_size);
+ for (int i = 0; i < init_size; i += 2)
+ init.append("10");
+ lc->params[ctx->id("INIT")] = Property::from_string(init);
+
replace_port(dff, ctx->id("D"), lc, ctx->id("I[0]"));
}
diff --git a/generic/examples/.gitignore b/generic/examples/.gitignore
index 38e95de5..ad2fba28 100644
--- a/generic/examples/.gitignore
+++ b/generic/examples/.gitignore
@@ -1,3 +1,6 @@
blinky.fasm
__pycache__
*.pyc
+pnrblinky.v
+/blinky_simtest
+*.vcd
diff --git a/generic/examples/bitstream.py b/generic/examples/bitstream.py
index 1ab94f0c..7f0b5c07 100644
--- a/generic/examples/bitstream.py
+++ b/generic/examples/bitstream.py
@@ -14,4 +14,4 @@ param_map = {
}
with open("blinky.fasm", "w") as f:
- write_fasm(ctx, param_map, f) \ No newline at end of file
+ write_fasm(ctx, param_map, f)
diff --git a/generic/examples/blinky.v b/generic/examples/blinky.v
index b7cb1b86..42becb72 100644
--- a/generic/examples/blinky.v
+++ b/generic/examples/blinky.v
@@ -1,9 +1,12 @@
-module top(input clk, output reg [7:0] leds);
+module top(input clk, rst, output reg [7:0] leds);
-reg [25:0] ctr;
+reg [7:0] ctr;
always @(posedge clk)
- ctr <= ctr + 1'b1;
+ if (rst)
+ ctr <= 8'h00;
+ else
+ ctr <= ctr + 1'b1;
-assign leds = ctr[25:18];
+assign leds = ctr;
-endmodule \ No newline at end of file
+endmodule
diff --git a/generic/examples/blinky_tb.v b/generic/examples/blinky_tb.v
new file mode 100644
index 00000000..f9925e6f
--- /dev/null
+++ b/generic/examples/blinky_tb.v
@@ -0,0 +1,38 @@
+`timescale 1ns / 1ps
+module blinky_tb;
+
+reg clk = 1'b0, rst = 1'b0;
+reg [7:0] ctr_gold = 8'h00;
+wire [7:0] ctr_gate;
+top dut_i(.clk(clk), .rst(rst), .leds(ctr_gate));
+
+task oneclk;
+ begin
+ clk = 1'b1;
+ #10;
+ clk = 1'b0;
+ #10;
+ end
+endtask
+
+initial begin
+ $dumpfile("blinky_simtest.vcd");
+ $dumpvars(0, blinky_tb);
+ #100;
+ rst = 1'b1;
+ repeat (5) oneclk;
+ #5
+ rst = 1'b0;
+ #5
+ repeat (500) begin
+ if (ctr_gold !== ctr_gate) begin
+ $display("mismatch gold=%b gate=%b", ctr_gold, ctr_gate);
+ $stop;
+ end
+ oneclk;
+ ctr_gold = ctr_gold + 1'b1;
+ end
+ $finish;
+end
+
+endmodule
diff --git a/generic/examples/simple.py b/generic/examples/simple.py
index 9339b68a..9379b505 100644
--- a/generic/examples/simple.py
+++ b/generic/examples/simple.py
@@ -9,6 +9,7 @@ for x in range(X):
for z in range(N):
ctx.addWire(name="X%dY%dZ%d_CLK" % (x, y, z), type="BEL_CLK", x=x, y=y)
ctx.addWire(name="X%dY%dZ%d_Q" % (x, y, z), type="BEL_Q", x=x, y=y)
+ ctx.addWire(name="X%dY%dZ%d_F" % (x, y, z), type="BEL_F", x=x, y=y)
for i in range(K):
ctx.addWire(name="X%dY%dZ%d_I%d" % (x, y, z, i), type="BEL_I", x=x, y=y)
# Local wires
@@ -29,6 +30,7 @@ for x in range(X):
ctx.addBelInput(bel="X%dY%d_SLICE%d" % (x, y, z), name="CLK", wire="X%dY%dZ%d_CLK" % (x, y, z))
for k in range(K):
ctx.addBelInput(bel="X%dY%d_SLICE%d" % (x, y, z), name="I[%d]" % k, wire="X%dY%dZ%d_I%d" % (x, y, z, k))
+ ctx.addBelOutput(bel="X%dY%d_SLICE%d" % (x, y, z), name="F", wire="X%dY%dZ%d_F" % (x, y, z))
ctx.addBelOutput(bel="X%dY%d_SLICE%d" % (x, y, z), name="Q", wire="X%dY%dZ%d_Q" % (x, y, z))
for x in range(X):
@@ -48,6 +50,9 @@ for x in range(X):
# Pips from bel outputs to locals
def create_output_pips(dst, offset, skip):
for i in range(offset % skip, N, skip):
+ src = "X%dY%dZ%d_F" % (x, y, i)
+ ctx.addPip(name="X%dY%d.%s.%s" % (x, y, src, dst), type="BEL_OUTPUT",
+ srcWire=src, dstWire=dst, delay=ctx.getDelayFromNS(0.05), loc=Loc(x, y, 0))
src = "X%dY%dZ%d_Q" % (x, y, i)
ctx.addPip(name="X%dY%d.%s.%s" % (x, y, src, dst), type="BEL_OUTPUT",
srcWire=src, dstWire=dst, delay=ctx.getDelayFromNS(0.05), loc=Loc(x, y, 0))
@@ -69,4 +74,4 @@ for x in range(X):
create_neighbour_pips(dst, x, y+1, (l + 4) % Sl, Sl)
create_neighbour_pips(dst, x+1, y-1, (l + 5) % Sl, Sl)
create_neighbour_pips(dst, x+1, y, (l + 6) % Sl, Sl)
- create_neighbour_pips(dst, x+1, y+1, (l + 7) % Sl, Sl) \ No newline at end of file
+ create_neighbour_pips(dst, x+1, y+1, (l + 7) % Sl, Sl)
diff --git a/generic/examples/simple.sh b/generic/examples/simple.sh
index 8ae903f9..76bc6168 100755
--- a/generic/examples/simple.sh
+++ b/generic/examples/simple.sh
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
set -ex
yosys -p "tcl ../synth/synth_generic.tcl 4 blinky.json" blinky.v
-${NEXTPNR:-../../nextpnr-generic} --pre-pack simple.py --pre-place simple_timing.py --json blinky.json --post-route bitstream.py
+${NEXTPNR:-../../nextpnr-generic} --pre-pack simple.py --pre-place simple_timing.py --json blinky.json --post-route bitstream.py --write pnrblinky.json
+yosys -p "read_verilog -lib ../synth/prims.v; read_json pnrblinky.json; dump -o blinky.il; show -format png -prefix blinky"
diff --git a/generic/examples/simple_timing.py b/generic/examples/simple_timing.py
index 2ccb197e..1067b556 100644
--- a/generic/examples/simple_timing.py
+++ b/generic/examples/simple_timing.py
@@ -1,15 +1,13 @@
for cname, cell in ctx.cells:
- if cell.type != "GENERIC_SLICE":
- continue
- if cname in ("$PACKER_GND", "$PACKER_VCC"):
- continue
- K = int(cell.params["K"])
- if int(cell.params["FF_USED"], 2) == 1:
- ctx.addCellTimingClock(cell=cname, port="CLK")
- for i in range(K):
- ctx.addCellTimingSetupHold(cell=cname, port="I[%d]" % i, clock="CLK",
- setup=ctx.getDelayFromNS(0.2), hold=ctx.getDelayFromNS(0))
- ctx.addCellTimingClockToOut(cell=cname, port="Q", clock="CLK", clktoq=ctx.getDelayFromNS(0.2))
- else:
- for i in range(K):
- ctx.addCellTimingDelay(cell=cname, fromPort="I[%d]" % i, toPort="Q", delay=ctx.getDelayFromNS(0.2)) \ No newline at end of file
+ if cell.type != "GENERIC_SLICE":
+ continue
+ if cname in ("$PACKER_GND", "$PACKER_VCC"):
+ continue
+ K = int(cell.params["K"])
+ ctx.addCellTimingClock(cell=cname, port="CLK")
+ for i in range(K):
+ ctx.addCellTimingSetupHold(cell=cname, port="I[%d]" % i, clock="CLK",
+ setup=ctx.getDelayFromNS(0.2), hold=ctx.getDelayFromNS(0))
+ ctx.addCellTimingClockToOut(cell=cname, port="Q", clock="CLK", clktoq=ctx.getDelayFromNS(0.2))
+ for i in range(K):
+ ctx.addCellTimingDelay(cell=cname, fromPort="I[%d]" % i, toPort="F", delay=ctx.getDelayFromNS(0.2))
diff --git a/generic/examples/simtest.sh b/generic/examples/simtest.sh
new file mode 100755
index 00000000..ef328914
--- /dev/null
+++ b/generic/examples/simtest.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+set -ex
+yosys -p "tcl ../synth/synth_generic.tcl 4 blinky.json" blinky.v
+${NEXTPNR:-../../nextpnr-generic} --no-iobs --pre-pack simple.py --pre-place simple_timing.py --json blinky.json --post-route bitstream.py --write pnrblinky.json
+yosys -p "read_json pnrblinky.json; write_verilog -noattr -norename pnrblinky.v"
+iverilog -o blinky_simtest ../synth/prims.v blinky_tb.v pnrblinky.v
+vvp -N ./blinky_simtest
diff --git a/generic/main.cc b/generic/main.cc
index 7dfc6aa7..bb780996 100644
--- a/generic/main.cc
+++ b/generic/main.cc
@@ -46,6 +46,7 @@ po::options_description GenericCommandHandler::getArchOptions()
{
po::options_description specific("Architecture specific options");
specific.add_options()("generic", "set device type to generic");
+ specific.add_options()("no-iobs", "disable automatic IO buffer insertion");
return specific;
}
@@ -59,7 +60,10 @@ std::unique_ptr<Context> GenericCommandHandler::createContext(std::unordered_map
if (arch_name != "generic")
log_error("Unsuported architecture '%s'.\n", arch_name.c_str());
}
- return std::unique_ptr<Context>(new Context(chipArgs));
+ auto ctx = std::unique_ptr<Context>(new Context(chipArgs));
+ if (vm.count("no-iobs"))
+ ctx->settings[ctx->id("disable_iobs")] = Property::State::S1;
+ return ctx;
}
int main(int argc, char *argv[])
diff --git a/generic/pack.cc b/generic/pack.cc
index 3dc12bc1..e92e04c5 100644
--- a/generic/pack.cc
+++ b/generic/pack.cc
@@ -150,20 +150,21 @@ static void pack_constants(Context *ctx)
log_info("Packing constants..\n");
std::unique_ptr<CellInfo> gnd_cell = create_generic_cell(ctx, ctx->id("GENERIC_SLICE"), "$PACKER_GND");
- gnd_cell->params[ctx->id("INIT")] = 0;
+ gnd_cell->params[ctx->id("INIT")] = Property(0, 1 << ctx->args.K);
std::unique_ptr<NetInfo> gnd_net = std::unique_ptr<NetInfo>(new NetInfo);
gnd_net->name = ctx->id("$PACKER_GND_NET");
gnd_net->driver.cell = gnd_cell.get();
- gnd_net->driver.port = ctx->id("Q");
- gnd_cell->ports.at(ctx->id("Q")).net = gnd_net.get();
+ gnd_net->driver.port = ctx->id("F");
+ gnd_cell->ports.at(ctx->id("F")).net = gnd_net.get();
std::unique_ptr<CellInfo> vcc_cell = create_generic_cell(ctx, ctx->id("GENERIC_SLICE"), "$PACKER_VCC");
- vcc_cell->params[ctx->id("INIT")] = 1;
+ // Fill with 1s
+ vcc_cell->params[ctx->id("INIT")] = Property(Property::S1).extract(0, (1 << ctx->args.K), Property::S1);
std::unique_ptr<NetInfo> vcc_net = std::unique_ptr<NetInfo>(new NetInfo);
vcc_net->name = ctx->id("$PACKER_VCC_NET");
vcc_net->driver.cell = vcc_cell.get();
- vcc_net->driver.port = ctx->id("Q");
- vcc_cell->ports.at(ctx->id("Q")).net = vcc_net.get();
+ vcc_net->driver.port = ctx->id("F");
+ vcc_cell->ports.at(ctx->id("F")).net = vcc_net.get();
std::vector<IdString> dead_nets;
@@ -249,6 +250,10 @@ static void pack_io(Context *ctx)
delete_nets.insert(net2->name);
}
}
+ } else if (bool_or_default(ctx->settings, ctx->id("disable_iobs"))) {
+ // No IO buffer insertion; just remove nextpnr_[io]buf
+ for (auto &p : ci->ports)
+ disconnect_port(ctx, ci, p.first);
} else {
// Create a GENERIC_IOB buffer
std::unique_ptr<CellInfo> ice_cell =
diff --git a/generic/synth/cells_map.v b/generic/synth/cells_map.v
index a6027534..1d0939e0 100644
--- a/generic/synth/cells_map.v
+++ b/generic/synth/cells_map.v
@@ -4,7 +4,9 @@ module \$lut (A, Y);
input [WIDTH-1:0] A;
output Y;
- LUT #(.K(`LUT_K), .INIT(LUT)) _TECHMAP_REPLACE_ (.I(A), .Q(Y));
+ localparam rep = 1<<(`LUT_K-WIDTH);
+
+ LUT #(.K(`LUT_K), .INIT({rep{LUT}})) _TECHMAP_REPLACE_ (.I(A), .Q(Y));
endmodule
module \$_DFF_P_ (input D, C, output Q); DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
diff --git a/generic/synth/prims.v b/generic/synth/prims.v
index 95fcfac7..ca445e6e 100644
--- a/generic/synth/prims.v
+++ b/generic/synth/prims.v
@@ -2,18 +2,27 @@
module LUT #(
parameter K = 4,
- parameter [2**K-1:0] INIT = 0,
+ parameter [2**K-1:0] INIT = 0
) (
input [K-1:0] I,
output Q
);
- assign Q = INIT[I];
+ wire [K-1:0] I_pd;
+
+ genvar ii;
+ generate
+ for (ii = 0; ii < K; ii = ii + 1'b1)
+ assign I_pd[ii] = (I[ii] === 1'bz) ? 1'b0 : I[ii];
+ endgenerate
+
+ assign Q = INIT[I_pd];
endmodule
module DFF (
input CLK, D,
output reg Q
);
+ initial Q = 1'b0;
always @(posedge CLK)
Q <= D;
endmodule
@@ -25,17 +34,16 @@ module GENERIC_SLICE #(
) (
input CLK,
input [K-1:0] I,
+ output F,
output Q
);
+ wire f_wire;
- wire lut_q;
- LUT #(.K(K), .INIT(INIT)) lut_i(.I(I), .Q(lut_q));
+ LUT #(.K(K), .INIT(INIT)) lut_i(.I(I), .Q(f_wire));
- generate if (FF_USED)
- DFF dff_i(.CLK(CLK), .D(lut_q), .Q(Q));
- else
- assign Q = lut_q;
- endgenerate
+ DFF dff_i(.CLK(CLK), .D(f_wire), .Q(Q));
+
+ assign F = f_wire;
endmodule
module GENERIC_IOB #(
@@ -56,4 +64,4 @@ module GENERIC_IOB #(
generate if (INPUT_USED)
assign O = PAD;
endgenerate
-endmodule \ No newline at end of file
+endmodule