diff options
-rw-r--r-- | ice40/chip.cc | 14 | ||||
-rw-r--r-- | ice40/chip.h | 2 | ||||
-rw-r--r-- | ice40/main.cc | 9 | ||||
-rw-r--r-- | ice40/pack_tests/io_wrapper.v | 169 | ||||
-rwxr-xr-x | ice40/pack_tests/test.sh | 4 | ||||
-rw-r--r-- | ice40/pcf.cc | 71 | ||||
-rw-r--r-- | ice40/pcf.h | 33 |
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 |