aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ice40/chip.cc14
-rw-r--r--ice40/chip.h2
-rw-r--r--ice40/main.cc9
-rw-r--r--ice40/pack_tests/io_wrapper.v169
-rwxr-xr-xice40/pack_tests/test.sh4
-rw-r--r--ice40/pcf.cc71
-rw-r--r--ice40/pcf.h33
7 files changed, 131 insertions, 171 deletions
diff --git a/ice40/chip.cc b/ice40/chip.cc
index 464b226c..267976eb 100644
--- a/ice40/chip.cc
+++ b/ice40/chip.cc
@@ -240,6 +240,20 @@ PipId Chip::getPipByName(IdString name) const
// -----------------------------------------------------------------------
+BelId Chip::getPackagePinBel(const std::string &pin) const
+{
+ for (int i = 0; i < package_info->num_pins; i++) {
+ if (package_info->pins[i].name == pin) {
+ BelId id;
+ id.index = package_info->pins[i].bel_index;
+ return id;
+ }
+ }
+ return BelId();
+}
+
+// -----------------------------------------------------------------------
+
void Chip::getBelPosition(BelId bel, float &x, float &y) const
{
assert(bel != BelId());
diff --git a/ice40/chip.h b/ice40/chip.h
index 7d5c9fbf..37cff038 100644
--- a/ice40/chip.h
+++ b/ice40/chip.h
@@ -693,6 +693,8 @@ struct Chip
return range;
}
+ BelId getPackagePinBel(const std::string &pin) const;
+
// -------------------------------------------------
void getBelPosition(BelId bel, float &x, float &y) const;
diff --git a/ice40/main.cc b/ice40/main.cc
index 7a0d92be..8ccec77b 100644
--- a/ice40/main.cc
+++ b/ice40/main.cc
@@ -30,6 +30,7 @@
#include "mainwindow.h"
#include "nextpnr.h"
#include "pack.h"
+#include "pcf.h"
#include "place.h"
#include "pybindings.h"
#include "route.h"
@@ -74,6 +75,8 @@ int main(int argc, char *argv[])
"python file to execute");
options.add_options()("json", po::value<std::string>(),
"JSON design file to ingest");
+ options.add_options()("pcf", po::value<std::string>(),
+ "PCF constraints file to ingest");
options.add_options()("asc", po::value<std::string>(),
"asc bitstream file to write");
options.add_options()("version,v", "show version");
@@ -205,6 +208,12 @@ int main(int argc, char *argv[])
std::istream *f = new std::ifstream(filename);
parse_json_file(f, filename, &design);
+
+ if (vm.count("pcf")) {
+ std::ifstream pcf(vm["pcf"].as<std::string>());
+ apply_pcf(&design, pcf);
+ }
+
pack_design(&design);
if (!vm.count("pack-only")) {
place_design(&design);
diff --git a/ice40/pack_tests/io_wrapper.v b/ice40/pack_tests/io_wrapper.v
deleted file mode 100644
index e10ec419..00000000
--- a/ice40/pack_tests/io_wrapper.v
+++ /dev/null
@@ -1,169 +0,0 @@
-module io_wrapper(input clk_pin, cen_pin, rst_pin, ina_pin, inb_pin,
- output outa_pin, outb_pin, outc_pin, outd_pin);
-
- wire clk, cen, rst, ina, inb, outa, outb, outc, outd;
-
- (* BEL="0_14_io1" *)
- SB_IO #(
- .PIN_TYPE(6'b 0000_01),
- .PULLUP(1'b0),
- .NEG_TRIGGER(1'b0)
- ) clk_iob (
- .PACKAGE_PIN(clk_pin),
- .LATCH_INPUT_VALUE(),
- .CLOCK_ENABLE(),
- .INPUT_CLK(),
- .OUTPUT_CLK(),
- .OUTPUT_ENABLE(),
- .D_OUT_0(),
- .D_OUT_1(),
- .D_IN_0(clk),
- .D_IN_1()
- );
-
- (* BEL="0_14_io0" *)
- SB_IO #(
- .PIN_TYPE(6'b 0000_01),
- .PULLUP(1'b0),
- .NEG_TRIGGER(1'b0)
- ) cen_iob (
- .PACKAGE_PIN(cen_pin),
- .LATCH_INPUT_VALUE(),
- .CLOCK_ENABLE(),
- .INPUT_CLK(),
- .OUTPUT_CLK(),
- .OUTPUT_ENABLE(),
- .D_OUT_0(),
- .D_OUT_1(),
- .D_IN_0(cen),
- .D_IN_1()
- );
-
- (* BEL="0_13_io1" *)
- SB_IO #(
- .PIN_TYPE(6'b 0000_01),
- .PULLUP(1'b0),
- .NEG_TRIGGER(1'b0)
- ) rst_iob (
- .PACKAGE_PIN(rst_pin),
- .LATCH_INPUT_VALUE(),
- .CLOCK_ENABLE(),
- .INPUT_CLK(),
- .OUTPUT_CLK(),
- .OUTPUT_ENABLE(),
- .D_OUT_0(),
- .D_OUT_1(),
- .D_IN_0(rst),
- .D_IN_1()
- );
-
- (* BEL="0_13_io0" *)
- SB_IO #(
- .PIN_TYPE(6'b 0000_01),
- .PULLUP(1'b0),
- .NEG_TRIGGER(1'b0)
- ) ina_iob (
- .PACKAGE_PIN(ina_pin),
- .LATCH_INPUT_VALUE(),
- .CLOCK_ENABLE(),
- .INPUT_CLK(),
- .OUTPUT_CLK(),
- .OUTPUT_ENABLE(),
- .D_OUT_0(),
- .D_OUT_1(),
- .D_IN_0(ina),
- .D_IN_1()
- );
-
- (* BEL="0_12_io1" *)
- SB_IO #(
- .PIN_TYPE(6'b 0000_01),
- .PULLUP(1'b0),
- .NEG_TRIGGER(1'b0)
- ) inb_iob (
- .PACKAGE_PIN(inb_pin),
- .LATCH_INPUT_VALUE(),
- .CLOCK_ENABLE(),
- .INPUT_CLK(),
- .OUTPUT_CLK(),
- .OUTPUT_ENABLE(),
- .D_OUT_0(),
- .D_OUT_1(),
- .D_IN_0(inb),
- .D_IN_1()
- );
-
- (* BEL="0_12_io0" *)
- SB_IO #(
- .PIN_TYPE(6'b 0110_01),
- .PULLUP(1'b0),
- .NEG_TRIGGER(1'b0)
- ) outa_iob (
- .PACKAGE_PIN(outa_pin),
- .LATCH_INPUT_VALUE(),
- .CLOCK_ENABLE(),
- .INPUT_CLK(),
- .OUTPUT_CLK(),
- .OUTPUT_ENABLE(),
- .D_OUT_0(outa),
- .D_OUT_1(),
- .D_IN_0(),
- .D_IN_1()
- );
-
- (* BEL="0_11_io1" *)
- SB_IO #(
- .PIN_TYPE(6'b 0110_01),
- .PULLUP(1'b0),
- .NEG_TRIGGER(1'b0)
- ) outb_iob (
- .PACKAGE_PIN(outb_pin),
- .LATCH_INPUT_VALUE(),
- .CLOCK_ENABLE(),
- .INPUT_CLK(),
- .OUTPUT_CLK(),
- .OUTPUT_ENABLE(),
- .D_OUT_0(outb),
- .D_OUT_1(),
- .D_IN_0(),
- .D_IN_1()
- );
-
- (* BEL="0_11_io0" *)
- SB_IO #(
- .PIN_TYPE(6'b 0110_01),
- .PULLUP(1'b0),
- .NEG_TRIGGER(1'b0)
- ) outc_iob (
- .PACKAGE_PIN(outc_pin),
- .LATCH_INPUT_VALUE(),
- .CLOCK_ENABLE(),
- .INPUT_CLK(),
- .OUTPUT_CLK(),
- .OUTPUT_ENABLE(),
- .D_OUT_0(outc),
- .D_OUT_1(),
- .D_IN_0(),
- .D_IN_1()
- );
-
- (* BEL="0_10_io1" *)
- SB_IO #(
- .PIN_TYPE(6'b 0110_01),
- .PULLUP(1'b0),
- .NEG_TRIGGER(1'b0)
- ) outd_iob (
- .PACKAGE_PIN(outd_pin),
- .LATCH_INPUT_VALUE(),
- .CLOCK_ENABLE(),
- .INPUT_CLK(),
- .OUTPUT_CLK(),
- .OUTPUT_ENABLE(),
- .D_OUT_0(outd),
- .D_OUT_1(),
- .D_IN_0(),
- .D_IN_1()
- );
-
- top top_i(.clk(clk), .rst(rst), .cen(cen), .ina(ina), .inb(inb), .outa(outa), .outb(outb), .outc(outc), .outd(outd));
-endmodule
diff --git a/ice40/pack_tests/test.sh b/ice40/pack_tests/test.sh
index dd1f345c..b36c01dc 100755
--- a/ice40/pack_tests/test.sh
+++ b/ice40/pack_tests/test.sh
@@ -1,8 +1,8 @@
#!/usr/bin/env bash
set -ex
NAME=${1%.v}
-yosys -p "synth_ice40 -nocarry -top io_wrapper; write_json ${NAME}.json" $1 io_wrapper.v
-../../nextpnr-ice40 --json ${NAME}.json --pack --asc ${NAME}.asc
+yosys -p "synth_ice40 -nocarry -top top; write_json ${NAME}.json" $1
+../../nextpnr-ice40 --json ${NAME}.json --pcf test.pcf --asc ${NAME}.asc
icebox_vlog -p test.pcf ${NAME}.asc > ${NAME}_out.v
yosys -p "read_verilog +/ice40/cells_sim.v;\
diff --git a/ice40/pcf.cc b/ice40/pcf.cc
new file mode 100644
index 00000000..75c32731
--- /dev/null
+++ b/ice40/pcf.cc
@@ -0,0 +1,71 @@
+/*
+ * nextpnr -- Next Generation Place and Route
+ *
+ * Copyright (C) 2018 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "pcf.h"
+#include <sstream>
+#include "log.h"
+
+NEXTPNR_NAMESPACE_BEGIN
+
+// Read a w
+
+// Apply PCF constraints to a pre-packing design
+void apply_pcf(Design *design, std::istream &in)
+{
+ if (!in)
+ log_error("failed to open PCF file");
+ std::string line;
+ while (std::getline(in, line)) {
+ size_t cstart = line.find("#");
+ if (cstart != std::string::npos)
+ line = line.substr(0, cstart);
+ std::stringstream ss(line);
+ std::vector<std::string> words;
+ std::string tmp;
+ while (ss >> tmp)
+ words.push_back(tmp);
+ if (words.size() == 0)
+ continue;
+ std::string cmd = words.at(0);
+ if (cmd == "set_io") {
+ size_t args_end = 1;
+ while (args_end < words.size() && words.at(args_end).at(0) == '-')
+ args_end++;
+ std::string cell = words.at(args_end);
+ std::string pin = words.at(args_end + 1);
+ auto fnd_cell = design->cells.find(cell);
+ if (fnd_cell == design->cells.end()) {
+ log_warning("unmatched pcf constraint %s\n", cell.c_str());
+ } else {
+ BelId pin_bel = design->chip.getPackagePinBel(pin);
+ if (pin_bel == BelId())
+ log_error("package does not have a pin named %s\n",
+ pin.c_str());
+ fnd_cell->second->attrs["BEL"] =
+ design->chip.getBelName(pin_bel).str();
+ log_info("constrained '%s' to bel '%s'\n", cell.c_str(),
+ fnd_cell->second->attrs["BEL"].c_str());
+ }
+ } else {
+ log_error("unsupported pcf command '%s'\n", cmd.c_str());
+ }
+ }
+}
+
+NEXTPNR_NAMESPACE_END
diff --git a/ice40/pcf.h b/ice40/pcf.h
new file mode 100644
index 00000000..c4a7d991
--- /dev/null
+++ b/ice40/pcf.h
@@ -0,0 +1,33 @@
+/*
+ * nextpnr -- Next Generation Place and Route
+ *
+ * Copyright (C) 2018 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef PCF_H
+#define PCF_H
+
+#include <iostream>
+#include "nextpnr.h"
+
+NEXTPNR_NAMESPACE_BEGIN
+
+// Apply PCF constraints to a pre-packing design
+void apply_pcf(Design *design, std::istream &in);
+
+NEXTPNR_NAMESPACE_END
+
+#endif // ROUTE_H