diff options
Diffstat (limited to 'generic')
-rw-r--r-- | generic/arch.cc | 102 | ||||
-rw-r--r-- | generic/arch.h | 5 | ||||
-rw-r--r-- | generic/arch_pybindings.cc | 2 | ||||
-rw-r--r-- | generic/cells.cc | 14 | ||||
-rw-r--r-- | generic/examples/.gitignore | 3 | ||||
-rw-r--r-- | generic/examples/bitstream.py | 2 | ||||
-rw-r--r-- | generic/examples/blinky.v | 13 | ||||
-rw-r--r-- | generic/examples/blinky_tb.v | 38 | ||||
-rw-r--r-- | generic/examples/simple.py | 7 | ||||
-rwxr-xr-x | generic/examples/simple.sh | 3 | ||||
-rw-r--r-- | generic/examples/simple_timing.py | 26 | ||||
-rwxr-xr-x | generic/examples/simtest.sh | 7 | ||||
-rw-r--r-- | generic/main.cc | 6 | ||||
-rw-r--r-- | generic/pack.cc | 17 | ||||
-rw-r--r-- | generic/synth/cells_map.v | 4 | ||||
-rw-r--r-- | generic/synth/prims.v | 28 |
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 |