aboutsummaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
Diffstat (limited to 'generic')
-rw-r--r--generic/arch.cc66
-rw-r--r--generic/arch.h5
-rw-r--r--generic/examples/.gitignore3
-rw-r--r--generic/examples/blinky.v13
-rw-r--r--generic/examples/blinky_tb.v38
-rwxr-xr-xgeneric/examples/simtest.sh7
-rw-r--r--generic/main.cc6
-rw-r--r--generic/pack.cc4
-rw-r--r--generic/synth/prims.v13
9 files changed, 126 insertions, 29 deletions
diff --git a/generic/arch.cc b/generic/arch.cc
index 14d15115..c1c01d26 100644
--- a/generic/arch.cc
+++ b/generic/arch.cc
@@ -27,6 +27,30 @@
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);
@@ -50,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)
@@ -75,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);
}
@@ -115,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); }
@@ -165,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);
}
@@ -187,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; }
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/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/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/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 69f248d2..19266aba 100644
--- a/generic/pack.cc
+++ b/generic/pack.cc
@@ -249,6 +249,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/prims.v b/generic/synth/prims.v
index 1148041c..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