ice40: Add a PCF parser

Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
David Shah 2018-06-13 12:30:15 +02:00
parent 5435a97024
commit de0918c287
7 changed files with 131 additions and 171 deletions

View File

@ -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());

View File

@ -693,6 +693,8 @@ struct Chip
return range;
}
BelId getPackagePinBel(const std::string &pin) const;
// -------------------------------------------------
void getBelPosition(BelId bel, float &x, float &y) const;

View File

@ -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);

View File

@ -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

View File

@ -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;\

71
ice40/pcf.cc Normal file
View File

@ -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

33
ice40/pcf.h Normal file
View File

@ -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