Merge branch 'master' into gqtech

This commit is contained in:
ZipCPU 2018-06-07 07:45:22 -04:00
commit 1ed5c641c1
21 changed files with 1402 additions and 1103 deletions

View File

@ -47,12 +47,10 @@ DisableFormat: false
ExperimentalAutoDetectBinPacking: false ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories: IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Regex: '<.*>'
Priority: 2
- Regex: '^(<|"(gtest|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1 Priority: 1
- Regex: '.*'
Priority: 2
IndentCaseLabels: false IndentCaseLabels: false
IndentWidth: 4 IndentWidth: 4
IndentWrappedFunctionNames: false IndentWrappedFunctionNames: false

1
.gitignore vendored
View File

@ -18,3 +18,4 @@ CMakeCache.txt
.*.swp .*.swp
a.out a.out
*.json *.json
build/

View File

@ -21,6 +21,7 @@ Building
- Use CMake to generate the Makefiles (only needs to be done when `CMakeLists.txt` changes) - Use CMake to generate the Makefiles (only needs to be done when `CMakeLists.txt` changes)
- For a debug build, run `cmake -DCMAKE_BUILD_TYPE=Debug .` - For a debug build, run `cmake -DCMAKE_BUILD_TYPE=Debug .`
- For a debug build with HX1K support only, run ` cmake -DCMAKE_BUILD_TYPE=Debug -DICE40_HX1K_ONLY=1 .`
- For a release build, run `cmake .` - For a release build, run `cmake .`
- Use Make to run the build itself - Use Make to run the build itself
- For all targets, just run `make` - For all targets, just run `make`

View File

@ -18,4 +18,3 @@
*/ */
#include "design.h" #include "design.h"

View File

@ -20,50 +20,52 @@
#ifndef DESIGN_H #ifndef DESIGN_H
#define DESIGN_H #define DESIGN_H
#include <stdint.h>
#include <assert.h> #include <assert.h>
#include <vector> #include <stdint.h>
#include <string> #include <string>
#include <unordered_set>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#include <vector>
// replace with proper IdString later // replace with proper IdString later
typedef std::string IdString; typedef std::string IdString;
// replace with haslib later // replace with haslib later
template<typename T> using pool = std::unordered_set<T>; template <typename T> using pool = std::unordered_set<T>;
template<typename T, typename U> using dict = std::unordered_map<T, U>; template <typename T, typename U> using dict = std::unordered_map<T, U>;
using std::vector; using std::vector;
struct GraphicElement struct GraphicElement
{ {
// This will control colour, and there should be separate // This will control colour, and there should be separate
// visibility controls in some cases also // visibility controls in some cases also
enum { enum
// Wires entirely inside tiles, e.g. between switchbox and bels {
G_LOCAL_WIRES, // Wires entirely inside tiles, e.g. between switchbox and bels
// Standard inter-tile routing G_LOCAL_WIRES,
G_GENERAL_WIRES, // Standard inter-tile routing
// Special inter-tile wires, e.g. carry chains G_GENERAL_WIRES,
G_DEDICATED_WIRES, // Special inter-tile wires, e.g. carry chains
G_BEL_OUTLINE, G_DEDICATED_WIRES,
G_SWITCHBOX_OUTLINE, G_BEL_OUTLINE,
G_TILE_OUTLINE, G_SWITCHBOX_OUTLINE,
G_BEL_PINS, G_TILE_OUTLINE,
G_SWITCHBOX_PINS, G_BEL_PINS,
G_BEL_MISC, G_SWITCHBOX_PINS,
G_TILE_MISC, G_BEL_MISC,
} style; G_TILE_MISC,
} style;
enum { enum
G_LINE, {
G_BOX, G_LINE,
G_CIRCLE, G_BOX,
G_LABEL G_CIRCLE,
} type; G_LABEL
} type;
float x1, y1, x2, y2, z; float x1, y1, x2, y2, z;
std::string text; std::string text;
}; };
#include "chip.h" #include "chip.h"
@ -72,56 +74,57 @@ struct CellInfo;
struct PortRef struct PortRef
{ {
CellInfo *cell; CellInfo *cell;
IdString port; IdString port;
}; };
struct NetInfo struct NetInfo
{ {
IdString name; IdString name;
PortRef driver; PortRef driver;
vector<PortRef> users; vector<PortRef> users;
dict<IdString, std::string> attrs; dict<IdString, std::string> attrs;
// wire -> (uphill_wire, delay) // wire -> (uphill_wire, delay)
dict<WireId, std::pair<WireId, DelayInfo>> wires; dict<WireId, std::pair<WireId, DelayInfo>> wires;
}; };
enum PortType enum PortType
{ {
PORT_IN = 0, PORT_IN = 0,
PORT_OUT = 1, PORT_OUT = 1,
PORT_INOUT = 2 PORT_INOUT = 2
}; };
struct PortInfo struct PortInfo
{ {
IdString name; IdString name;
NetInfo *net; NetInfo *net;
PortType type; PortType type;
}; };
struct CellInfo struct CellInfo
{ {
IdString name, type; IdString name, type;
dict<IdString, PortInfo> ports; dict<IdString, PortInfo> ports;
dict<IdString, std::string> attrs, params; dict<IdString, std::string> attrs, params;
BelId bel; BelId bel;
// cell_port -> bel_pin // cell_port -> bel_pin
dict<IdString, IdString> pins; dict<IdString, IdString> pins;
}; };
struct Design struct Design
{ {
struct Chip chip; struct Chip chip;
Design(ChipArgs args) : chip(args) { Design(ChipArgs args) : chip(args)
// ... {
} // ...
}
dict<IdString, NetInfo*> nets; dict<IdString, NetInfo *> nets;
dict<IdString, CellInfo*> cells; dict<IdString, CellInfo *> cells;
}; };
#endif #endif

View File

@ -18,24 +18,89 @@
* *
*/ */
#include "design.h"
#include "chip.h" #include "chip.h"
#include "design.h"
#include "emb.h"
// include after design.h/chip.h
#include "pybindings.h" #include "pybindings.h"
// Required to determine concatenated module name (which differs for different archs) // Required to determine concatenated module name (which differs for different
#define PASTER(x, y) x ## _ ## y // archs)
#define EVALUATOR(x, y) PASTER(x,y) #define PASTER(x, y) x##_##y
#define EVALUATOR(x, y) PASTER(x, y)
#define MODULE_NAME EVALUATOR(nextpnrpy, ARCHNAME) #define MODULE_NAME EVALUATOR(nextpnrpy, ARCHNAME)
#define PYINIT_MODULE_NAME EVALUATOR(&PyInit_nextpnrpy, ARCHNAME) #define PYINIT_MODULE_NAME EVALUATOR(&PyInit_nextpnrpy, ARCHNAME)
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x) #define TOSTRING(x) STRINGIFY(x)
// Architecture-specific bindings should be created in the below function, which must be implemented in all // Architecture-specific bindings should be created in the below function, which
// architectures // must be implemented in all architectures
void arch_wrap_python(); void arch_wrap_python();
BOOST_PYTHON_MODULE (MODULE_NAME) { bool operator==(const PortRef &a, const PortRef &b)
{
return (a.cell == b.cell) && (a.port == b.port);
}
BOOST_PYTHON_MODULE(MODULE_NAME)
{
class_<GraphicElement>("GraphicElement")
.def_readwrite("style", &GraphicElement::style)
.def_readwrite("type", &GraphicElement::type)
.def_readwrite("x1", &GraphicElement::x1)
.def_readwrite("y1", &GraphicElement::y1)
.def_readwrite("x2", &GraphicElement::x2)
.def_readwrite("y2", &GraphicElement::y2)
.def_readwrite("text", &GraphicElement::text);
class_<PortRef>("PortRef")
.def_readwrite("cell", &PortRef::cell)
.def_readwrite("port", &PortRef::port);
class_<NetInfo, NetInfo *>("NetInfo")
.def_readwrite("name", &NetInfo::name)
.def_readwrite("driver", &NetInfo::driver)
.def_readwrite("users", &NetInfo::users)
.def_readwrite("attrs", &NetInfo::attrs)
.def_readwrite("wires", &NetInfo::wires);
WRAP_MAP(decltype(NetInfo::attrs), "IdStrMap");
class_<vector<PortRef>>("PortRefVector")
.def(vector_indexing_suite<vector<PortRef>>());
enum_<PortType>("PortType")
.value("PORT_IN", PORT_IN)
.value("PORT_OUT", PORT_OUT)
.value("PORT_INOUT", PORT_INOUT)
.export_values();
class_<PortInfo>("PortInfo")
.def_readwrite("name", &PortInfo::name)
.def_readwrite("net", &PortInfo::net)
.def_readwrite("type", &PortInfo::type);
class_<CellInfo, CellInfo *>("CellInfo")
.def_readwrite("name", &CellInfo::name)
.def_readwrite("type", &CellInfo::type)
.def_readwrite("ports", &CellInfo::ports)
.def_readwrite("attrs", &CellInfo::attrs)
.def_readwrite("params", &CellInfo::params)
.def_readwrite("bel", &CellInfo::bel)
.def_readwrite("pins", &CellInfo::pins);
WRAP_MAP(decltype(CellInfo::ports), "IdPortMap");
// WRAP_MAP(decltype(CellInfo::pins), "IdIdMap");
class_<Design, Design *>("Design", no_init)
.def_readwrite("chip", &Design::chip)
.def_readwrite("nets", &Design::nets)
.def_readwrite("cells", &Design::cells);
WRAP_MAP(decltype(Design::nets), "IdNetMap");
WRAP_MAP(decltype(Design::cells), "IdCellMap");
arch_wrap_python(); arch_wrap_python();
} }
@ -44,35 +109,47 @@ void arch_appendinittab()
PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME);
} }
void execute_python_file(const char *executable, const char* python_file) static wchar_t *program;
void init_python(const char *executable)
{ {
wchar_t *program = Py_DecodeLocale(executable, NULL); program = Py_DecodeLocale(executable, NULL);
if (program == NULL) { if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode executable filename\n"); fprintf(stderr, "Fatal error: cannot decode executable filename\n");
exit(1); exit(1);
} }
try try {
{
PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME);
emb::append_inittab();
Py_SetProgramName(program); Py_SetProgramName(program);
Py_Initialize(); Py_Initialize();
PyImport_ImportModule(TOSTRING(MODULE_NAME));
FILE* fp = fopen(python_file, "r"); } catch (boost::python::error_already_set const &) {
if (fp == NULL) {
fprintf(stderr, "Fatal error: file not found %s\n",python_file);
exit(1);
}
PyRun_SimpleFile(fp , python_file);
fclose(fp);
Py_Finalize();
PyMem_RawFree(program);
}
catch(boost::python::error_already_set const &)
{
// Parse and output the exception // Parse and output the exception
std::string perror_str = parse_python_exception(); std::string perror_str = parse_python_exception();
std::cout << "Error in Python: " << perror_str << std::endl; std::cout << "Error in Python: " << perror_str << std::endl;
} }
} }
void deinit_python()
{
Py_Finalize();
PyMem_RawFree(program);
}
void execute_python_file(const char *python_file)
{
try {
FILE *fp = fopen(python_file, "r");
if (fp == NULL) {
fprintf(stderr, "Fatal error: file not found %s\n", python_file);
exit(1);
}
PyRun_SimpleFile(fp, python_file);
fclose(fp);
} catch (boost::python::error_already_set const &) {
// Parse and output the exception
std::string perror_str = parse_python_exception();
std::cout << "Error in Python: " << perror_str << std::endl;
}
}

View File

@ -20,67 +20,98 @@
#ifndef COMMON_PYBINDINGS_H #ifndef COMMON_PYBINDINGS_H
#define COMMON_PYBINDINGS_H #define COMMON_PYBINDINGS_H
#include <utility>
#include <stdexcept> #include "pycontainers.h"
#include <Python.h>
#include <boost/python.hpp> #include <boost/python.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp> #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp> #include <stdexcept>
#include <boost/python/suite/indexing/map_indexing_suite.hpp> #include <utility>
using namespace boost::python; using namespace boost::python;
/* /*
A wrapper for a Pythonised nextpnr Iterator. The actual class wrapped is a A wrapper to enable custom type/ID to/from string conversions
pair<Iterator, Iterator> containing (current, end) */
*/ template <typename T> struct string_wrapper
{
template <typename F> struct from_pystring_converter
{
from_pystring_converter()
{
converter::registry::push_back(&convertible, &construct,
boost::python::type_id<T>());
};
template<typename T> static void *convertible(PyObject *object)
struct iterator_wrapper { {
typedef decltype(*(std::declval<T>())) value_t; return PyUnicode_Check(object) ? object : 0;
static value_t next(std::pair<T, T> &iter) {
if (iter.first != iter.second) {
value_t val = *iter.first;
++iter.first;
return val;
} else {
PyErr_SetString(PyExc_StopIteration, "End of range reached");
boost::python::throw_error_already_set();
// Should be unreachable, but prevent control may reach end of non-void
throw std::runtime_error("unreachable");
} }
}
static void wrap(const char *python_name) { static void construct(PyObject *object,
class_<std::pair<T, T>>(python_name, no_init) converter::rvalue_from_python_stage1_data *data)
.def("__next__", next); {
} const wchar_t *value = PyUnicode_AsUnicode(object);
const std::wstring value_ws(value);
if (value == 0)
throw_error_already_set();
void *storage =
((boost::python::converter::rvalue_from_python_storage<T> *)
data)
->storage.bytes;
new (storage) T(fn(std::string(value_ws.begin(), value_ws.end())));
data->convertible = storage;
}
static F fn;
};
template <typename F> struct to_str_wrapper
{
static F fn;
std::string str(T &x) { return fn(x); }
};
template <typename F1, typename F2>
static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn)
{
from_pystring_converter<F2>::fn = from_str_fn;
from_pystring_converter<F2>();
to_str_wrapper<F1>::fn = to_str_fn;
class_<T>(type_name, no_init).def("__str__", to_str_wrapper<F1>::str);
};
}; };
/*
A wrapper for a nextpnr Range. Ranges should have two functions, begin()
and end() which return iterator-like objects supporting ++, * and !=
Full STL iterator semantics are not required, unlike the standard Boost wrappers
*/
template<typename T>
struct range_wrapper {
typedef decltype(std::declval<T>().begin()) iterator_t;
static std::pair<iterator_t, iterator_t> iter(T &range) {
return std::make_pair(range.begin(), range.end());
}
static void wrap(const char *range_name, const char *iter_name) {
class_<T>(range_name, no_init)
.def("__iter__", iter);
iterator_wrapper<iterator_t>().wrap(iter_name);
}
};
#define WRAP_RANGE(t) range_wrapper<t##Range>().wrap(#t "Range", #t "Iterator")
void execute_python_file(const char *executable, const char* python_file);
std::string parse_python_exception(); std::string parse_python_exception();
template <typename Tn> void python_export_global(const char *name, Tn &x)
{
PyObject *m, *d;
m = PyImport_AddModule("__main__");
if (m == NULL)
return;
d = PyModule_GetDict(m);
try {
PyObject *p = incref(object(boost::ref(x)).ptr());
PyDict_SetItemString(d, name, p);
} catch (boost::python::error_already_set const &) {
// Parse and output the exception
std::string perror_str = parse_python_exception();
std::cout << "Error in Python: " << perror_str << std::endl;
std::terminate();
}
};
void init_python(const char *executable);
void deinit_python();
void execute_python_file(const char *python_file);
std::string parse_python_exception();
void arch_appendinittab(); void arch_appendinittab();
#endif /* end of include guard: COMMON_PYBINDINGS_HH */ #endif /* end of include guard: COMMON_PYBINDINGS_HH */

129
common/pycontainers.h Normal file
View File

@ -0,0 +1,129 @@
/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2018 Clifford Wolf <clifford@clifford.at>
* Copyright (C) 2018 David Shah <dave@ds0.me>
*
* 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 COMMON_PYCONTAINERS_H
#define COMMON_PYCONTAINERS_H
#include <utility>
#include <stdexcept>
#include <type_traits>
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
using namespace boost::python;
/*
A wrapper for a Pythonised nextpnr Iterator. The actual class wrapped is a
pair<Iterator, Iterator> containing (current, end)
*/
template<typename T, typename P>
struct iterator_wrapper {
typedef decltype(*(std::declval<T>())) value_t;
static value_t next(std::pair <T, T> &iter) {
if (iter.first != iter.second) {
value_t val = *iter.first;
++iter.first;
return val;
} else {
PyErr_SetString(PyExc_StopIteration, "End of range reached");
boost::python::throw_error_already_set();
// Should be unreachable, but prevent control may reach end of non-void
throw std::runtime_error("unreachable");
}
}
static void wrap(const char *python_name) {
class_ < std::pair < T, T >> (python_name, no_init)
.def("__next__", next, P());
}
};
/*
A wrapper for a nextpnr Range. Ranges should have two functions, begin()
and end() which return iterator-like objects supporting ++, * and !=
Full STL iterator semantics are not required, unlike the standard Boost wrappers
*/
template<typename T, typename P = return_value_policy<return_by_value>>
struct range_wrapper {
typedef decltype(std::declval<T>().begin()) iterator_t;
static std::pair <iterator_t, iterator_t> iter(T &range) {
return std::make_pair(range.begin(), range.end());
}
static void wrap(const char *range_name, const char *iter_name) {
class_<T>(range_name, no_init)
.def("__iter__", iter);
iterator_wrapper<iterator_t, P>().wrap(iter_name);
}
typedef iterator_wrapper<iterator_t, P> iter_wrap;
};
#define WRAP_RANGE(t) range_wrapper<t##Range>().wrap(#t "Range", #t "Iterator")
/*
Wrapper for a map, either an unordered_map, regular map or dict
*/
inline void KeyError() { PyErr_SetString(PyExc_KeyError, "Key not found"); }
template<typename T>
struct map_wrapper {
typedef typename std::remove_cv<typename std::remove_reference<typename T::key_type>::type>::type K;
typedef typename T::mapped_type V;
typedef typename T::value_type KV;
static V &get(T &x, K const &i) {
if (x.find(i) != x.end()) return x.at(i);
KeyError();
std::terminate();
}
static void set(T &x, K const &i, V const &v) {
x[i] = v;
}
static void del(T const &x, K const &i) {
if (x.find(i) != x.end()) x.erase(i);
else KeyError();
std::terminate();
}
static void wrap(const char *map_name, const char *kv_name, const char *iter_name) {
class_<KV>(kv_name)
.def_readonly("first", &KV::first)
.def_readwrite("second", &KV::second);
typedef range_wrapper<T, return_value_policy<copy_non_const_reference>> rw;
typename rw::iter_wrap().wrap(iter_name);
class_<T>(map_name, no_init)
.def("__iter__", rw::iter)
.def("__len__", &T::size)
.def("__getitem__", get, return_internal_reference<>())
.def("__setitem__", set, with_custodian_and_ward<1,2>());
}
};
#define WRAP_MAP(t, name) map_wrapper<t>().wrap(#name, #name "KeyValue", #name "Iterator")
#endif

View File

@ -57,5 +57,6 @@ bool check_all_nets_driven(Design *design) {
} }
if (debug) log_info(" Verified!\n"); if (debug) log_info(" Verified!\n");
return true;
} }

View File

@ -19,6 +19,4 @@
#include "chip.h" #include "chip.h"
Chip::Chip(ChipArgs) Chip::Chip(ChipArgs) {}
{
}

View File

@ -24,10 +24,10 @@
struct DelayInfo struct DelayInfo
{ {
float delay = 0; float delay = 0;
float raiseDelay() { return delay; } float raiseDelay() { return delay; }
float fallDelay() { return delay; } float fallDelay() { return delay; }
}; };
typedef IdString BelType; typedef IdString BelType;
@ -45,8 +45,8 @@ typedef IdString PipId;
struct BelPin struct BelPin
{ {
BelId bel; BelId bel;
PortPin pin; PortPin pin;
}; };
struct ChipArgs struct ChipArgs
@ -55,48 +55,48 @@ struct ChipArgs
struct Chip struct Chip
{ {
Chip(ChipArgs args); Chip(ChipArgs args);
BelId getBelByName(IdString name) const; BelId getBelByName(IdString name) const;
IdString getBelName(BelId bel) const; IdString getBelName(BelId bel) const;
void bindBel(BelId bel, IdString cell); void bindBel(BelId bel, IdString cell);
void unbindBel(BelId bel); void unbindBel(BelId bel);
bool checkBelAvail(BelId bel) const; bool checkBelAvail(BelId bel) const;
const vector<BelId> &getBels() const; const vector<BelId> &getBels() const;
const vector<BelId> &getBelsByType(BelType type) const; const vector<BelId> &getBelsByType(BelType type) const;
BelType getBelType(BelId bel) const; BelType getBelType(BelId bel) const;
WireId getWireBelPin(BelId bel, PortPin pin) const; WireId getWireBelPin(BelId bel, PortPin pin) const;
BelPin getBelPinUphill(WireId wire) const; BelPin getBelPinUphill(WireId wire) const;
const vector<BelPin> &getBelPinsDownhill(WireId wire) const; const vector<BelPin> &getBelPinsDownhill(WireId wire) const;
WireId getWireByName(IdString name) const; WireId getWireByName(IdString name) const;
IdString getWireName(WireId wire) const; IdString getWireName(WireId wire) const;
void bindWire(WireId bel, IdString net); void bindWire(WireId bel, IdString net);
void unbindWire(WireId bel); void unbindWire(WireId bel);
bool checkWireAvail(WireId bel) const; bool checkWireAvail(WireId bel) const;
const vector<WireId> &getWires() const; const vector<WireId> &getWires() const;
PipId getPipByName(IdString name) const; PipId getPipByName(IdString name) const;
IdString getPipName(PipId pip) const; IdString getPipName(PipId pip) const;
void bindPip(PipId bel, IdString net); void bindPip(PipId bel, IdString net);
void unbindPip(PipId bel); void unbindPip(PipId bel);
bool checkPipAvail(PipId bel) const; bool checkPipAvail(PipId bel) const;
const vector<PipId> &getPips() const; const vector<PipId> &getPips() const;
WireId getPipSrcWire(PipId pip) const; WireId getPipSrcWire(PipId pip) const;
WireId getPipDstWire(PipId pip) const; WireId getPipDstWire(PipId pip) const;
DelayInfo getPipDelay(PipId pip) const; DelayInfo getPipDelay(PipId pip) const;
const vector<PipId> &getPipsDownhill(WireId wire) const; const vector<PipId> &getPipsDownhill(WireId wire) const;
const vector<PipId> &getPipsUphill(WireId wire) const; const vector<PipId> &getPipsUphill(WireId wire) const;
const vector<PipId> &getWireAliases(WireId wire) const; const vector<PipId> &getWireAliases(WireId wire) const;
void getBelPosition(BelId bel, float &x, float &y) const; void getBelPosition(BelId bel, float &x, float &y) const;
void getWirePosition(WireId wire, float &x, float &y) const; void getWirePosition(WireId wire, float &x, float &y) const;
void getPipPosition(PipId pip, float &x, float &y) const; void getPipPosition(PipId pip, float &x, float &y) const;
vector<GraphicElement> getBelGraphics(BelId bel) const; vector<GraphicElement> getBelGraphics(BelId bel) const;
vector<GraphicElement> getWireGraphics(WireId wire) const; vector<GraphicElement> getWireGraphics(WireId wire) const;
vector<GraphicElement> getPipGraphics(PipId pip) const; vector<GraphicElement> getPipGraphics(PipId pip) const;
vector<GraphicElement> getFrameGraphics() const; vector<GraphicElement> getFrameGraphics() const;
}; };
#endif #endif

View File

@ -17,15 +17,15 @@
* *
*/ */
#include <QApplication>
#include "design.h" #include "design.h"
#include "mainwindow.h" #include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
Design design(ChipArgs{}); Design design(ChipArgs{});
QApplication a(argc, argv); QApplication a(argc, argv);
MainWindow w; MainWindow w;
w.show(); w.show();

View File

@ -18,10 +18,10 @@
* *
*/ */
#include "design.h"
#include "chip.h" #include "chip.h"
#include "design.h"
// include after design.h/chip.h
#include "pybindings.h" #include "pybindings.h"
void arch_wrap_python() { void arch_wrap_python() { class_<ChipArgs>("ChipArgs"); }
class_<ChipArgs>("ChipArgs");
}

View File

@ -11,9 +11,6 @@ MainWindow::MainWindow(QWidget *parent) :
ui(new Ui::MainWindow) ui(new Ui::MainWindow)
{ {
ui->setupUi(this); ui->setupUi(this);
emb::append_inittab();
arch_appendinittab();
Py_Initialize();
PyImport_ImportModule("emb"); PyImport_ImportModule("emb");
write = [this] (std::string s) { write = [this] (std::string s) {
@ -27,7 +24,6 @@ MainWindow::MainWindow(QWidget *parent) :
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
Py_Finalize();
delete ui; delete ui;
} }

View File

@ -23,460 +23,470 @@
IdString belTypeToId(BelType type) IdString belTypeToId(BelType type)
{ {
if (type == TYPE_ICESTORM_LC) if (type == TYPE_ICESTORM_LC)
return "ICESTORM_LC"; return "ICESTORM_LC";
if (type == TYPE_ICESTORM_RAM) if (type == TYPE_ICESTORM_RAM)
return "ICESTORM_RAM"; return "ICESTORM_RAM";
if (type == TYPE_SB_IO) if (type == TYPE_SB_IO)
return "SB_IO"; return "SB_IO";
return IdString(); return IdString();
} }
BelType belTypeFromId(IdString id) BelType belTypeFromId(IdString id)
{ {
if (id == "ICESTORM_LC") if (id == "ICESTORM_LC")
return TYPE_ICESTORM_LC; return TYPE_ICESTORM_LC;
if (id == "ICESTORM_RAM") if (id == "ICESTORM_RAM")
return TYPE_ICESTORM_RAM; return TYPE_ICESTORM_RAM;
if (id == "SB_IO") if (id == "SB_IO")
return TYPE_SB_IO; return TYPE_SB_IO;
return TYPE_NIL; return TYPE_NIL;
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
IdString PortPinToId(PortPin type) IdString PortPinToId(PortPin type)
{ {
#define X(t) if (type == PIN_##t) return #t; #define X(t) \
if (type == PIN_##t) \
return #t;
X(IN_0) X(IN_0)
X(IN_1) X(IN_1)
X(IN_2) X(IN_2)
X(IN_3) X(IN_3)
X(O) X(O)
X(LO) X(LO)
X(CIN) X(CIN)
X(COUT) X(COUT)
X(CEN) X(CEN)
X(CLK) X(CLK)
X(SR) X(SR)
X(MASK_0) X(MASK_0)
X(MASK_1) X(MASK_1)
X(MASK_2) X(MASK_2)
X(MASK_3) X(MASK_3)
X(MASK_4) X(MASK_4)
X(MASK_5) X(MASK_5)
X(MASK_6) X(MASK_6)
X(MASK_7) X(MASK_7)
X(MASK_8) X(MASK_8)
X(MASK_9) X(MASK_9)
X(MASK_10) X(MASK_10)
X(MASK_11) X(MASK_11)
X(MASK_12) X(MASK_12)
X(MASK_13) X(MASK_13)
X(MASK_14) X(MASK_14)
X(MASK_15) X(MASK_15)
X(RDATA_0) X(RDATA_0)
X(RDATA_1) X(RDATA_1)
X(RDATA_2) X(RDATA_2)
X(RDATA_3) X(RDATA_3)
X(RDATA_4) X(RDATA_4)
X(RDATA_5) X(RDATA_5)
X(RDATA_6) X(RDATA_6)
X(RDATA_7) X(RDATA_7)
X(RDATA_8) X(RDATA_8)
X(RDATA_9) X(RDATA_9)
X(RDATA_10) X(RDATA_10)
X(RDATA_11) X(RDATA_11)
X(RDATA_12) X(RDATA_12)
X(RDATA_13) X(RDATA_13)
X(RDATA_14) X(RDATA_14)
X(RDATA_15) X(RDATA_15)
X(WDATA_0) X(WDATA_0)
X(WDATA_1) X(WDATA_1)
X(WDATA_2) X(WDATA_2)
X(WDATA_3) X(WDATA_3)
X(WDATA_4) X(WDATA_4)
X(WDATA_5) X(WDATA_5)
X(WDATA_6) X(WDATA_6)
X(WDATA_7) X(WDATA_7)
X(WDATA_8) X(WDATA_8)
X(WDATA_9) X(WDATA_9)
X(WDATA_10) X(WDATA_10)
X(WDATA_11) X(WDATA_11)
X(WDATA_12) X(WDATA_12)
X(WDATA_13) X(WDATA_13)
X(WDATA_14) X(WDATA_14)
X(WDATA_15) X(WDATA_15)
X(WADDR_0) X(WADDR_0)
X(WADDR_1) X(WADDR_1)
X(WADDR_2) X(WADDR_2)
X(WADDR_3) X(WADDR_3)
X(WADDR_4) X(WADDR_4)
X(WADDR_5) X(WADDR_5)
X(WADDR_6) X(WADDR_6)
X(WADDR_7) X(WADDR_7)
X(WADDR_8) X(WADDR_8)
X(WADDR_9) X(WADDR_9)
X(WADDR_10) X(WADDR_10)
X(RADDR_0) X(RADDR_0)
X(RADDR_1) X(RADDR_1)
X(RADDR_2) X(RADDR_2)
X(RADDR_3) X(RADDR_3)
X(RADDR_4) X(RADDR_4)
X(RADDR_5) X(RADDR_5)
X(RADDR_6) X(RADDR_6)
X(RADDR_7) X(RADDR_7)
X(RADDR_8) X(RADDR_8)
X(RADDR_9) X(RADDR_9)
X(RADDR_10) X(RADDR_10)
X(WCLK) X(WCLK)
X(WCLKE) X(WCLKE)
X(WE) X(WE)
X(RCLK) X(RCLK)
X(RCLKE) X(RCLKE)
X(RE) X(RE)
X(PACKAGE_PIN) X(PACKAGE_PIN)
X(LATCH_INPUT_VALUE) X(LATCH_INPUT_VALUE)
X(CLOCK_ENABLE) X(CLOCK_ENABLE)
X(INPUT_CLK) X(INPUT_CLK)
X(OUTPUT_CLK) X(OUTPUT_CLK)
X(OUTPUT_ENABLE) X(OUTPUT_ENABLE)
X(D_OUT_0) X(D_OUT_0)
X(D_OUT_1) X(D_OUT_1)
X(D_IN_0) X(D_IN_0)
X(D_IN_1) X(D_IN_1)
#undef X #undef X
return IdString(); return IdString();
} }
PortPin PortPinFromId(IdString id) PortPin PortPinFromId(IdString id)
{ {
#define X(t) if (id == #t) return PIN_##t; #define X(t) \
if (id == #t) \
return PIN_##t;
X(IN_0) X(IN_0)
X(IN_1) X(IN_1)
X(IN_2) X(IN_2)
X(IN_3) X(IN_3)
X(O) X(O)
X(LO) X(LO)
X(CIN) X(CIN)
X(COUT) X(COUT)
X(CEN) X(CEN)
X(CLK) X(CLK)
X(SR) X(SR)
X(MASK_0) X(MASK_0)
X(MASK_1) X(MASK_1)
X(MASK_2) X(MASK_2)
X(MASK_3) X(MASK_3)
X(MASK_4) X(MASK_4)
X(MASK_5) X(MASK_5)
X(MASK_6) X(MASK_6)
X(MASK_7) X(MASK_7)
X(MASK_8) X(MASK_8)
X(MASK_9) X(MASK_9)
X(MASK_10) X(MASK_10)
X(MASK_11) X(MASK_11)
X(MASK_12) X(MASK_12)
X(MASK_13) X(MASK_13)
X(MASK_14) X(MASK_14)
X(MASK_15) X(MASK_15)
X(RDATA_0) X(RDATA_0)
X(RDATA_1) X(RDATA_1)
X(RDATA_2) X(RDATA_2)
X(RDATA_3) X(RDATA_3)
X(RDATA_4) X(RDATA_4)
X(RDATA_5) X(RDATA_5)
X(RDATA_6) X(RDATA_6)
X(RDATA_7) X(RDATA_7)
X(RDATA_8) X(RDATA_8)
X(RDATA_9) X(RDATA_9)
X(RDATA_10) X(RDATA_10)
X(RDATA_11) X(RDATA_11)
X(RDATA_12) X(RDATA_12)
X(RDATA_13) X(RDATA_13)
X(RDATA_14) X(RDATA_14)
X(RDATA_15) X(RDATA_15)
X(WDATA_0) X(WDATA_0)
X(WDATA_1) X(WDATA_1)
X(WDATA_2) X(WDATA_2)
X(WDATA_3) X(WDATA_3)
X(WDATA_4) X(WDATA_4)
X(WDATA_5) X(WDATA_5)
X(WDATA_6) X(WDATA_6)
X(WDATA_7) X(WDATA_7)
X(WDATA_8) X(WDATA_8)
X(WDATA_9) X(WDATA_9)
X(WDATA_10) X(WDATA_10)
X(WDATA_11) X(WDATA_11)
X(WDATA_12) X(WDATA_12)
X(WDATA_13) X(WDATA_13)
X(WDATA_14) X(WDATA_14)
X(WDATA_15) X(WDATA_15)
X(WADDR_0) X(WADDR_0)
X(WADDR_1) X(WADDR_1)
X(WADDR_2) X(WADDR_2)
X(WADDR_3) X(WADDR_3)
X(WADDR_4) X(WADDR_4)
X(WADDR_5) X(WADDR_5)
X(WADDR_6) X(WADDR_6)
X(WADDR_7) X(WADDR_7)
X(WADDR_8) X(WADDR_8)
X(WADDR_9) X(WADDR_9)
X(WADDR_10) X(WADDR_10)
X(RADDR_0) X(RADDR_0)
X(RADDR_1) X(RADDR_1)
X(RADDR_2) X(RADDR_2)
X(RADDR_3) X(RADDR_3)
X(RADDR_4) X(RADDR_4)
X(RADDR_5) X(RADDR_5)
X(RADDR_6) X(RADDR_6)
X(RADDR_7) X(RADDR_7)
X(RADDR_8) X(RADDR_8)
X(RADDR_9) X(RADDR_9)
X(RADDR_10) X(RADDR_10)
X(WCLK) X(WCLK)
X(WCLKE) X(WCLKE)
X(WE) X(WE)
X(RCLK) X(RCLK)
X(RCLKE) X(RCLKE)
X(RE) X(RE)
X(PACKAGE_PIN) X(PACKAGE_PIN)
X(LATCH_INPUT_VALUE) X(LATCH_INPUT_VALUE)
X(CLOCK_ENABLE) X(CLOCK_ENABLE)
X(INPUT_CLK) X(INPUT_CLK)
X(OUTPUT_CLK) X(OUTPUT_CLK)
X(OUTPUT_ENABLE) X(OUTPUT_ENABLE)
X(D_OUT_0) X(D_OUT_0)
X(D_OUT_1) X(D_OUT_1)
X(D_IN_0) X(D_IN_0)
X(D_IN_1) X(D_IN_1)
#undef X #undef X
return PIN_NIL; return PIN_NIL;
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
Chip::Chip(ChipArgs args) Chip::Chip(ChipArgs args)
{ {
if (args.type == ChipArgs::LP384) { #ifdef ICE40_HX1K_ONLY
chip_info = chip_info_384; if (args.type == ChipArgs::HX1K) {
return; chip_info = chip_info_1k;
} else if (args.type == ChipArgs::LP1K || args.type == ChipArgs::HX1K) { return;
chip_info = chip_info_1k; }
return; #else
} else if (args.type == ChipArgs::UP5K) { if (args.type == ChipArgs::LP384) {
chip_info = chip_info_5k; chip_info = chip_info_384;
return; return;
} else if (args.type == ChipArgs::LP8K || args.type == ChipArgs::HX8K) { } else if (args.type == ChipArgs::LP1K || args.type == ChipArgs::HX1K) {
chip_info = chip_info_8k; chip_info = chip_info_1k;
return; return;
} else { } else if (args.type == ChipArgs::UP5K) {
fprintf(stderr, "Unsupported chip type\n"); chip_info = chip_info_5k;
exit(EXIT_FAILURE); return;
} } else if (args.type == ChipArgs::LP8K || args.type == ChipArgs::HX8K) {
chip_info = chip_info_8k;
return;
} else {
fprintf(stderr, "Unsupported chip type\n");
exit(EXIT_FAILURE);
}
#endif
abort(); abort();
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
BelId Chip::getBelByName(IdString name) const BelId Chip::getBelByName(IdString name) const
{ {
BelId ret; BelId ret;
if (bel_by_name.empty()) { if (bel_by_name.empty()) {
for (int i = 0; i < chip_info.num_bels; i++) for (int i = 0; i < chip_info.num_bels; i++)
bel_by_name[chip_info.bel_data[i].name] = i; bel_by_name[chip_info.bel_data[i].name] = i;
} }
auto it = bel_by_name.find(name); auto it = bel_by_name.find(name);
if (it != bel_by_name.end()) if (it != bel_by_name.end())
ret.index = it->second; ret.index = it->second;
return ret; return ret;
} }
WireId Chip::getWireBelPin(BelId bel, PortPin pin) const WireId Chip::getWireBelPin(BelId bel, PortPin pin) const
{ {
// FIXME // FIXME
return WireId(); return WireId();
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
WireId Chip::getWireByName(IdString name) const WireId Chip::getWireByName(IdString name) const
{ {
WireId ret; WireId ret;
if (wire_by_name.empty()) { if (wire_by_name.empty()) {
for (int i = 0; i < chip_info.num_wires; i++) for (int i = 0; i < chip_info.num_wires; i++)
wire_by_name[chip_info.wire_data[i].name] = i; wire_by_name[chip_info.wire_data[i].name] = i;
} }
auto it = wire_by_name.find(name); auto it = wire_by_name.find(name);
if (it != wire_by_name.end()) if (it != wire_by_name.end())
ret.index = it->second; ret.index = it->second;
return ret; return ret;
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
PipId Chip::getPipByName(IdString name) const PipId Chip::getPipByName(IdString name) const
{ {
PipId ret; PipId ret;
if (pip_by_name.empty()) { if (pip_by_name.empty()) {
for (int i = 0; i < chip_info.num_pips; i++) { for (int i = 0; i < chip_info.num_pips; i++) {
PipId pip; PipId pip;
pip.index = i; pip.index = i;
pip_by_name[getPipName(pip)] = i; pip_by_name[getPipName(pip)] = i;
} }
} }
auto it = pip_by_name.find(name); auto it = pip_by_name.find(name);
if (it != pip_by_name.end()) if (it != pip_by_name.end())
ret.index = it->second; ret.index = it->second;
return ret; return ret;
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
void Chip::getBelPosition(BelId bel, float &x, float &y) const void Chip::getBelPosition(BelId bel, float &x, float &y) const
{ {
assert(!bel.nil()); assert(!bel.nil());
x = chip_info.bel_data[bel.index].x; x = chip_info.bel_data[bel.index].x;
y = chip_info.bel_data[bel.index].y; y = chip_info.bel_data[bel.index].y;
} }
void Chip::getWirePosition(WireId wire, float &x, float &y) const void Chip::getWirePosition(WireId wire, float &x, float &y) const
{ {
assert(!wire.nil()); assert(!wire.nil());
x = chip_info.wire_data[wire.index].x; x = chip_info.wire_data[wire.index].x;
y = chip_info.wire_data[wire.index].y; y = chip_info.wire_data[wire.index].y;
} }
void Chip::getPipPosition(PipId pip, float &x, float &y) const void Chip::getPipPosition(PipId pip, float &x, float &y) const
{ {
assert(!pip.nil()); assert(!pip.nil());
x = chip_info.pip_data[pip.index].x; x = chip_info.pip_data[pip.index].x;
y = chip_info.pip_data[pip.index].y; y = chip_info.pip_data[pip.index].y;
} }
vector<GraphicElement> Chip::getBelGraphics(BelId bel) const vector<GraphicElement> Chip::getBelGraphics(BelId bel) const
{ {
vector<GraphicElement> ret; vector<GraphicElement> ret;
auto bel_type = getBelType(bel); auto bel_type = getBelType(bel);
if (bel_type == TYPE_ICESTORM_LC) { if (bel_type == TYPE_ICESTORM_LC) {
GraphicElement el; GraphicElement el;
el.type = GraphicElement::G_BOX; el.type = GraphicElement::G_BOX;
el.x1 = chip_info.bel_data[bel.index].x + 0.1; el.x1 = chip_info.bel_data[bel.index].x + 0.1;
el.x2 = chip_info.bel_data[bel.index].x + 0.9; el.x2 = chip_info.bel_data[bel.index].x + 0.9;
el.y1 = chip_info.bel_data[bel.index].y + 0.10 + (chip_info.bel_data[bel.index].z) * (0.8/8); el.y1 = chip_info.bel_data[bel.index].y + 0.10 +
el.y2 = chip_info.bel_data[bel.index].y + 0.18 + (chip_info.bel_data[bel.index].z) * (0.8/8); (chip_info.bel_data[bel.index].z) * (0.8 / 8);
el.z = 0; el.y2 = chip_info.bel_data[bel.index].y + 0.18 +
ret.push_back(el); (chip_info.bel_data[bel.index].z) * (0.8 / 8);
} el.z = 0;
ret.push_back(el);
}
if (bel_type == TYPE_SB_IO) { if (bel_type == TYPE_SB_IO) {
if (chip_info.bel_data[bel.index].x == 0 || chip_info.bel_data[bel.index].x == chip_info.width-1) if (chip_info.bel_data[bel.index].x == 0 ||
{ chip_info.bel_data[bel.index].x == chip_info.width - 1) {
GraphicElement el; GraphicElement el;
el.type = GraphicElement::G_BOX; el.type = GraphicElement::G_BOX;
el.x1 = chip_info.bel_data[bel.index].x + 0.1; el.x1 = chip_info.bel_data[bel.index].x + 0.1;
el.x2 = chip_info.bel_data[bel.index].x + 0.9; el.x2 = chip_info.bel_data[bel.index].x + 0.9;
if (chip_info.bel_data[bel.index].z == 0) { if (chip_info.bel_data[bel.index].z == 0) {
el.y1 = chip_info.bel_data[bel.index].y + 0.10; el.y1 = chip_info.bel_data[bel.index].y + 0.10;
el.y2 = chip_info.bel_data[bel.index].y + 0.45; el.y2 = chip_info.bel_data[bel.index].y + 0.45;
} else { } else {
el.y1 = chip_info.bel_data[bel.index].y + 0.55; el.y1 = chip_info.bel_data[bel.index].y + 0.55;
el.y2 = chip_info.bel_data[bel.index].y + 0.90; el.y2 = chip_info.bel_data[bel.index].y + 0.90;
} }
el.z = 0; el.z = 0;
ret.push_back(el); ret.push_back(el);
} } else {
else GraphicElement el;
{ el.type = GraphicElement::G_BOX;
GraphicElement el; if (chip_info.bel_data[bel.index].z == 0) {
el.type = GraphicElement::G_BOX; el.x1 = chip_info.bel_data[bel.index].x + 0.10;
if (chip_info.bel_data[bel.index].z == 0) { el.x2 = chip_info.bel_data[bel.index].x + 0.45;
el.x1 = chip_info.bel_data[bel.index].x + 0.10; } else {
el.x2 = chip_info.bel_data[bel.index].x + 0.45; el.x1 = chip_info.bel_data[bel.index].x + 0.55;
} else { el.x2 = chip_info.bel_data[bel.index].x + 0.90;
el.x1 = chip_info.bel_data[bel.index].x + 0.55; }
el.x2 = chip_info.bel_data[bel.index].x + 0.90; el.y1 = chip_info.bel_data[bel.index].y + 0.1;
} el.y2 = chip_info.bel_data[bel.index].y + 0.9;
el.y1 = chip_info.bel_data[bel.index].y + 0.1; el.z = 0;
el.y2 = chip_info.bel_data[bel.index].y + 0.9; ret.push_back(el);
el.z = 0; }
ret.push_back(el); }
}
}
if (bel_type == TYPE_ICESTORM_RAM) { if (bel_type == TYPE_ICESTORM_RAM) {
GraphicElement el; GraphicElement el;
el.type = GraphicElement::G_BOX; el.type = GraphicElement::G_BOX;
el.x1 = chip_info.bel_data[bel.index].x + 0.1; el.x1 = chip_info.bel_data[bel.index].x + 0.1;
el.x2 = chip_info.bel_data[bel.index].x + 0.9; el.x2 = chip_info.bel_data[bel.index].x + 0.9;
el.y1 = chip_info.bel_data[bel.index].y + 0.1; el.y1 = chip_info.bel_data[bel.index].y + 0.1;
el.y2 = chip_info.bel_data[bel.index].y + 1.9; el.y2 = chip_info.bel_data[bel.index].y + 1.9;
el.z = 0; el.z = 0;
ret.push_back(el); ret.push_back(el);
} }
return ret; return ret;
} }
vector<GraphicElement> Chip::getWireGraphics(WireId wire) const vector<GraphicElement> Chip::getWireGraphics(WireId wire) const
{ {
vector<GraphicElement> ret; vector<GraphicElement> ret;
// FIXME // FIXME
return ret; return ret;
} }
vector<GraphicElement> Chip::getPipGraphics(PipId pip) const vector<GraphicElement> Chip::getPipGraphics(PipId pip) const
{ {
vector<GraphicElement> ret; vector<GraphicElement> ret;
// FIXME // FIXME
return ret; return ret;
} }
vector<GraphicElement> Chip::getFrameGraphics() const vector<GraphicElement> Chip::getFrameGraphics() const
{ {
vector<GraphicElement> ret; vector<GraphicElement> ret;
for (int x = 0; x <= chip_info.width; x++) for (int x = 0; x <= chip_info.width; x++)
for (int y = 0; y <= chip_info.height; y++) for (int y = 0; y <= chip_info.height; y++) {
{ GraphicElement el;
GraphicElement el; el.type = GraphicElement::G_LINE;
el.type = GraphicElement::G_LINE; el.x1 = x - 0.05, el.x2 = x + 0.05, el.y1 = y, el.y2 = y, el.z = 0;
el.x1 = x - 0.05, el.x2 = x + 0.05, el.y1 = y, el.y2 = y, el.z = 0; ret.push_back(el);
ret.push_back(el); el.x1 = x, el.x2 = x, el.y1 = y - 0.05, el.y2 = y + 0.05, el.z = 0;
el.x1 = x, el.x2 = x, el.y1 = y - 0.05, el.y2 = y + 0.05, el.z = 0; ret.push_back(el);
ret.push_back(el); }
}
return ret; return ret;
} }

View File

@ -24,20 +24,20 @@
struct DelayInfo struct DelayInfo
{ {
float delay = 0; float delay = 0;
float raiseDelay() { return delay; } float raiseDelay() { return delay; }
float fallDelay() { return delay; } float fallDelay() { return delay; }
}; };
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
enum BelType enum BelType
{ {
TYPE_NIL, TYPE_NIL,
TYPE_ICESTORM_LC, TYPE_ICESTORM_LC,
TYPE_ICESTORM_RAM, TYPE_ICESTORM_RAM,
TYPE_SB_IO TYPE_SB_IO
}; };
IdString belTypeToId(BelType type); IdString belTypeToId(BelType type);
@ -45,113 +45,113 @@ BelType belTypeFromId(IdString id);
enum PortPin enum PortPin
{ {
PIN_NIL, PIN_NIL,
PIN_IN_0, PIN_IN_0,
PIN_IN_1, PIN_IN_1,
PIN_IN_2, PIN_IN_2,
PIN_IN_3, PIN_IN_3,
PIN_O, PIN_O,
PIN_LO, PIN_LO,
PIN_CIN, PIN_CIN,
PIN_COUT, PIN_COUT,
PIN_CEN, PIN_CEN,
PIN_CLK, PIN_CLK,
PIN_SR, PIN_SR,
PIN_MASK_0, PIN_MASK_0,
PIN_MASK_1, PIN_MASK_1,
PIN_MASK_2, PIN_MASK_2,
PIN_MASK_3, PIN_MASK_3,
PIN_MASK_4, PIN_MASK_4,
PIN_MASK_5, PIN_MASK_5,
PIN_MASK_6, PIN_MASK_6,
PIN_MASK_7, PIN_MASK_7,
PIN_MASK_8, PIN_MASK_8,
PIN_MASK_9, PIN_MASK_9,
PIN_MASK_10, PIN_MASK_10,
PIN_MASK_11, PIN_MASK_11,
PIN_MASK_12, PIN_MASK_12,
PIN_MASK_13, PIN_MASK_13,
PIN_MASK_14, PIN_MASK_14,
PIN_MASK_15, PIN_MASK_15,
PIN_RDATA_0, PIN_RDATA_0,
PIN_RDATA_1, PIN_RDATA_1,
PIN_RDATA_2, PIN_RDATA_2,
PIN_RDATA_3, PIN_RDATA_3,
PIN_RDATA_4, PIN_RDATA_4,
PIN_RDATA_5, PIN_RDATA_5,
PIN_RDATA_6, PIN_RDATA_6,
PIN_RDATA_7, PIN_RDATA_7,
PIN_RDATA_8, PIN_RDATA_8,
PIN_RDATA_9, PIN_RDATA_9,
PIN_RDATA_10, PIN_RDATA_10,
PIN_RDATA_11, PIN_RDATA_11,
PIN_RDATA_12, PIN_RDATA_12,
PIN_RDATA_13, PIN_RDATA_13,
PIN_RDATA_14, PIN_RDATA_14,
PIN_RDATA_15, PIN_RDATA_15,
PIN_WDATA_0, PIN_WDATA_0,
PIN_WDATA_1, PIN_WDATA_1,
PIN_WDATA_2, PIN_WDATA_2,
PIN_WDATA_3, PIN_WDATA_3,
PIN_WDATA_4, PIN_WDATA_4,
PIN_WDATA_5, PIN_WDATA_5,
PIN_WDATA_6, PIN_WDATA_6,
PIN_WDATA_7, PIN_WDATA_7,
PIN_WDATA_8, PIN_WDATA_8,
PIN_WDATA_9, PIN_WDATA_9,
PIN_WDATA_10, PIN_WDATA_10,
PIN_WDATA_11, PIN_WDATA_11,
PIN_WDATA_12, PIN_WDATA_12,
PIN_WDATA_13, PIN_WDATA_13,
PIN_WDATA_14, PIN_WDATA_14,
PIN_WDATA_15, PIN_WDATA_15,
PIN_WADDR_0, PIN_WADDR_0,
PIN_WADDR_1, PIN_WADDR_1,
PIN_WADDR_2, PIN_WADDR_2,
PIN_WADDR_3, PIN_WADDR_3,
PIN_WADDR_4, PIN_WADDR_4,
PIN_WADDR_5, PIN_WADDR_5,
PIN_WADDR_6, PIN_WADDR_6,
PIN_WADDR_7, PIN_WADDR_7,
PIN_WADDR_8, PIN_WADDR_8,
PIN_WADDR_9, PIN_WADDR_9,
PIN_WADDR_10, PIN_WADDR_10,
PIN_RADDR_0, PIN_RADDR_0,
PIN_RADDR_1, PIN_RADDR_1,
PIN_RADDR_2, PIN_RADDR_2,
PIN_RADDR_3, PIN_RADDR_3,
PIN_RADDR_4, PIN_RADDR_4,
PIN_RADDR_5, PIN_RADDR_5,
PIN_RADDR_6, PIN_RADDR_6,
PIN_RADDR_7, PIN_RADDR_7,
PIN_RADDR_8, PIN_RADDR_8,
PIN_RADDR_9, PIN_RADDR_9,
PIN_RADDR_10, PIN_RADDR_10,
PIN_WCLK, PIN_WCLK,
PIN_WCLKE, PIN_WCLKE,
PIN_WE, PIN_WE,
PIN_RCLK, PIN_RCLK,
PIN_RCLKE, PIN_RCLKE,
PIN_RE, PIN_RE,
PIN_PACKAGE_PIN, PIN_PACKAGE_PIN,
PIN_LATCH_INPUT_VALUE, PIN_LATCH_INPUT_VALUE,
PIN_CLOCK_ENABLE, PIN_CLOCK_ENABLE,
PIN_INPUT_CLK, PIN_INPUT_CLK,
PIN_OUTPUT_CLK, PIN_OUTPUT_CLK,
PIN_OUTPUT_ENABLE, PIN_OUTPUT_ENABLE,
PIN_D_OUT_0, PIN_D_OUT_0,
PIN_D_OUT_1, PIN_D_OUT_1,
PIN_D_IN_0, PIN_D_IN_0,
PIN_D_IN_1 PIN_D_IN_1
}; };
IdString PortPinToId(PortPin type); IdString PortPinToId(PortPin type);
@ -159,47 +159,46 @@ PortPin PortPinFromId(IdString id);
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
struct BelInfoPOD struct BelInfoPOD
{ {
const char *name; const char *name;
BelType type; BelType type;
int8_t x, y, z; int8_t x, y, z;
}; };
struct BelPortPOD struct BelPortPOD
{ {
int32_t bel_index; int32_t bel_index;
PortPin port; PortPin port;
}; };
struct PipInfoPOD struct PipInfoPOD
{ {
int32_t src, dst; int32_t src, dst;
float delay; float delay;
int8_t x, y; int8_t x, y;
}; };
struct WireInfoPOD struct WireInfoPOD
{ {
const char *name; const char *name;
int num_uphill, num_downhill; int num_uphill, num_downhill;
int *pips_uphill, *pips_downhill; int *pips_uphill, *pips_downhill;
int num_bels_downhill; int num_bels_downhill;
BelPortPOD bel_uphill; BelPortPOD bel_uphill;
BelPortPOD *bels_downhill; BelPortPOD *bels_downhill;
float x, y; float x, y;
}; };
struct ChipInfoPOD struct ChipInfoPOD
{ {
int width, height; int width, height;
int num_bels, num_wires, num_pips; int num_bels, num_wires, num_pips;
BelInfoPOD *bel_data; BelInfoPOD *bel_data;
WireInfoPOD *wire_data; WireInfoPOD *wire_data;
PipInfoPOD *pip_data; PipInfoPOD *pip_data;
}; };
extern ChipInfoPOD chip_info_384; extern ChipInfoPOD chip_info_384;
@ -211,248 +210,256 @@ extern ChipInfoPOD chip_info_8k;
struct BelId struct BelId
{ {
int32_t index = -1; int32_t index = -1;
bool nil() const { bool nil() const { return index < 0; }
return index < 0;
}
bool operator==(const BelId &other) const { return index == other.index; } bool operator==(const BelId &other) const { return index == other.index; }
bool operator!=(const BelId &other) const { return index != other.index; } bool operator!=(const BelId &other) const { return index != other.index; }
}; };
struct WireId struct WireId
{ {
int32_t index = -1; int32_t index = -1;
bool nil() const { bool nil() const { return index < 0; }
return index < 0;
}
bool operator==(const WireId &other) const { return index == other.index; } bool operator==(const WireId &other) const { return index == other.index; }
bool operator!=(const WireId &other) const { return index != other.index; } bool operator!=(const WireId &other) const { return index != other.index; }
}; };
struct PipId struct PipId
{ {
int32_t index = -1; int32_t index = -1;
bool nil() const { bool nil() const { return index < 0; }
return index < 0;
}
bool operator==(const PipId &other) const { return index == other.index; } bool operator==(const PipId &other) const { return index == other.index; }
bool operator!=(const PipId &other) const { return index != other.index; } bool operator!=(const PipId &other) const { return index != other.index; }
}; };
struct BelPin struct BelPin
{ {
BelId bel; BelId bel;
PortPin pin; PortPin pin;
}; };
namespace std namespace std {
template <> struct hash<BelId>
{ {
template<> struct hash<BelId> std::size_t operator()(const BelId &bel) const noexcept
{ {
std::size_t operator()(const BelId &bel) const noexcept return bel.index;
{ }
return bel.index; };
}
};
template<> struct hash<WireId> template <> struct hash<WireId>
{ {
std::size_t operator()(const WireId &wire) const noexcept std::size_t operator()(const WireId &wire) const noexcept
{ {
return wire.index; return wire.index;
} }
}; };
template<> struct hash<PipId> template <> struct hash<PipId>
{ {
std::size_t operator()(const PipId &wire) const noexcept std::size_t operator()(const PipId &wire) const noexcept
{ {
return wire.index; return wire.index;
} }
}; };
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
struct BelIterator struct BelIterator
{ {
int cursor; int cursor;
void operator++() { cursor++; } void operator++() { cursor++; }
bool operator!=(const BelIterator &other) const { return cursor != other.cursor; } bool operator!=(const BelIterator &other) const
{
return cursor != other.cursor;
}
BelId operator*() const { BelId operator*() const
BelId ret; {
ret.index = cursor; BelId ret;
return ret; ret.index = cursor;
} return ret;
}
}; };
struct BelRange struct BelRange
{ {
BelIterator b, e; BelIterator b, e;
BelIterator begin() const { return b; } BelIterator begin() const { return b; }
BelIterator end() const { return e; } BelIterator end() const { return e; }
}; };
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
struct BelPinIterator struct BelPinIterator
{ {
BelPortPOD *ptr = nullptr; BelPortPOD *ptr = nullptr;
void operator++() { ptr++; } void operator++() { ptr++; }
bool operator!=(const BelPinIterator &other) const { return ptr != other.ptr; } bool operator!=(const BelPinIterator &other) const
{
return ptr != other.ptr;
}
BelPin operator*() const { BelPin operator*() const
BelPin ret; {
ret.bel.index = ptr->bel_index; BelPin ret;
ret.pin = ptr->port; ret.bel.index = ptr->bel_index;
return ret; ret.pin = ptr->port;
} return ret;
}
}; };
struct BelPinRange struct BelPinRange
{ {
BelPinIterator b, e; BelPinIterator b, e;
BelPinIterator begin() const { return b; } BelPinIterator begin() const { return b; }
BelPinIterator end() const { return e; } BelPinIterator end() const { return e; }
}; };
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
struct WireIterator struct WireIterator
{ {
int cursor = -1; int cursor = -1;
void operator++() { cursor++; } void operator++() { cursor++; }
bool operator!=(const WireIterator &other) const { return cursor != other.cursor; } bool operator!=(const WireIterator &other) const
{
return cursor != other.cursor;
}
WireId operator*() const { WireId operator*() const
WireId ret; {
ret.index = cursor; WireId ret;
return ret; ret.index = cursor;
} return ret;
}
}; };
struct WireRange struct WireRange
{ {
WireIterator b, e; WireIterator b, e;
WireIterator begin() const { return b; } WireIterator begin() const { return b; }
WireIterator end() const { return e; } WireIterator end() const { return e; }
}; };
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
struct AllPipIterator struct AllPipIterator
{ {
int cursor = -1; int cursor = -1;
void operator++() { cursor++; } void operator++() { cursor++; }
bool operator!=(const AllPipIterator &other) const { return cursor != other.cursor; } bool operator!=(const AllPipIterator &other) const
{
return cursor != other.cursor;
}
PipId operator*() const { PipId operator*() const
PipId ret; {
ret.index = cursor; PipId ret;
return ret; ret.index = cursor;
} return ret;
}
}; };
struct AllPipRange struct AllPipRange
{ {
AllPipIterator b, e; AllPipIterator b, e;
AllPipIterator begin() const { return b; } AllPipIterator begin() const { return b; }
AllPipIterator end() const { return e; } AllPipIterator end() const { return e; }
}; };
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
struct PipIterator struct PipIterator
{ {
int *cursor = nullptr; int *cursor = nullptr;
void operator++() { cursor++; } void operator++() { cursor++; }
bool operator!=(const PipIterator &other) const { return cursor != other.cursor; } bool operator!=(const PipIterator &other) const
{
return cursor != other.cursor;
}
PipId operator*() const { PipId operator*() const
PipId ret; {
ret.index = *cursor; PipId ret;
return ret; ret.index = *cursor;
} return ret;
}
}; };
struct PipRange struct PipRange
{ {
PipIterator b, e; PipIterator b, e;
PipIterator begin() const { return b; } PipIterator begin() const { return b; }
PipIterator end() const { return e; } PipIterator end() const { return e; }
}; };
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
struct ChipArgs struct ChipArgs
{ {
enum { enum
NONE, {
LP384, NONE,
LP1K, LP384,
LP8K, LP1K,
HX1K, LP8K,
HX8K, HX1K,
UP5K HX8K,
} type = NONE; UP5K
} type = NONE;
}; };
struct Chip struct Chip
{ {
ChipInfoPOD chip_info; ChipInfoPOD chip_info;
mutable dict<IdString, int> bel_by_name; mutable dict<IdString, int> bel_by_name;
mutable dict<IdString, int> wire_by_name; mutable dict<IdString, int> wire_by_name;
mutable dict<IdString, int> pip_by_name; mutable dict<IdString, int> pip_by_name;
Chip(ChipArgs args); Chip(ChipArgs args);
// ------------------------------------------------- // -------------------------------------------------
BelId getBelByName(IdString name) const; BelId getBelByName(IdString name) const;
IdString getBelName(BelId bel) const IdString getBelName(BelId bel) const
{ {
assert(!bel.nil()); assert(!bel.nil());
return chip_info.bel_data[bel.index].name; return chip_info.bel_data[bel.index].name;
} }
void bindBel(BelId bel, IdString cell) void bindBel(BelId bel, IdString cell) {}
{
}
void unbindBel(BelId bel) void unbindBel(BelId bel) {}
{
}
bool checkBelAvail(BelId bel) const bool checkBelAvail(BelId bel) const {}
{
}
BelRange getBels() const BelRange getBels() const
{ {
BelRange range; BelRange range;
range.b.cursor = 0; range.b.cursor = 0;
range.e.cursor = chip_info.num_bels; range.e.cursor = chip_info.num_bels;
return range; return range;
} }
BelRange getBelsByType(BelType type) const BelRange getBelsByType(BelType type) const
{ {
BelRange range; BelRange range;
// FIXME // FIXME
#if 0 #if 0
if (type == "TYPE_A") { if (type == "TYPE_A") {
range.b.cursor = bels_type_a_begin; range.b.cursor = bels_type_a_begin;
@ -460,161 +467,155 @@ struct Chip
} }
... ...
#endif #endif
return range; return range;
} }
BelType getBelType(BelId bel) const BelType getBelType(BelId bel) const
{ {
assert(!bel.nil()); assert(!bel.nil());
return chip_info.bel_data[bel.index].type; return chip_info.bel_data[bel.index].type;
} }
WireId getWireBelPin(BelId bel, PortPin pin) const; WireId getWireBelPin(BelId bel, PortPin pin) const;
BelPin getBelPinUphill(WireId wire) const BelPin getBelPinUphill(WireId wire) const
{ {
BelPin ret; BelPin ret;
assert(!wire.nil()); assert(!wire.nil());
if (chip_info.wire_data[wire.index].bel_uphill.bel_index >= 0) { if (chip_info.wire_data[wire.index].bel_uphill.bel_index >= 0) {
ret.bel.index = chip_info.wire_data[wire.index].bel_uphill.bel_index; ret.bel.index =
ret.pin = chip_info.wire_data[wire.index].bel_uphill.port; chip_info.wire_data[wire.index].bel_uphill.bel_index;
} ret.pin = chip_info.wire_data[wire.index].bel_uphill.port;
}
return ret; return ret;
} }
BelPinRange getBelPinsDownhill(WireId wire) const BelPinRange getBelPinsDownhill(WireId wire) const
{ {
BelPinRange range; BelPinRange range;
assert(!wire.nil()); assert(!wire.nil());
range.b.ptr = chip_info.wire_data[wire.index].bels_downhill; range.b.ptr = chip_info.wire_data[wire.index].bels_downhill;
range.e.ptr = range.b.ptr + chip_info.wire_data[wire.index].num_bels_downhill; range.e.ptr =
return range; range.b.ptr + chip_info.wire_data[wire.index].num_bels_downhill;
} return range;
}
// ------------------------------------------------- // -------------------------------------------------
WireId getWireByName(IdString name) const; WireId getWireByName(IdString name) const;
IdString getWireName(WireId wire) const IdString getWireName(WireId wire) const
{ {
assert(!wire.nil()); assert(!wire.nil());
return chip_info.wire_data[wire.index].name; return chip_info.wire_data[wire.index].name;
} }
void bindWire(WireId bel, IdString net) void bindWire(WireId bel, IdString net) {}
{
}
void unbindWire(WireId bel) void unbindWire(WireId bel) {}
{
}
bool checkWireAvail(WireId bel) const bool checkWireAvail(WireId bel) const {}
{
}
WireRange getWires() const WireRange getWires() const
{ {
WireRange range; WireRange range;
range.b.cursor = 0; range.b.cursor = 0;
range.e.cursor = chip_info.num_wires; range.e.cursor = chip_info.num_wires;
return range; return range;
} }
// ------------------------------------------------- // -------------------------------------------------
PipId getPipByName(IdString name) const; PipId getPipByName(IdString name) const;
IdString getPipName(PipId pip) const IdString getPipName(PipId pip) const
{ {
assert(!pip.nil()); assert(!pip.nil());
std::string src_name = chip_info.wire_data[chip_info.pip_data[pip.index].src].name; std::string src_name =
std::string dst_name = chip_info.wire_data[chip_info.pip_data[pip.index].dst].name; chip_info.wire_data[chip_info.pip_data[pip.index].src].name;
return src_name + "->" + dst_name; std::string dst_name =
} chip_info.wire_data[chip_info.pip_data[pip.index].dst].name;
return src_name + "->" + dst_name;
}
void bindPip(PipId bel, IdString net) void bindPip(PipId bel, IdString net) {}
{
}
void unbindPip(PipId bel) void unbindPip(PipId bel) {}
{
}
bool checkPipAvail(PipId bel) const bool checkPipAvail(PipId bel) const {}
{
}
AllPipRange getPips() const AllPipRange getPips() const
{ {
AllPipRange range; AllPipRange range;
range.b.cursor = 0; range.b.cursor = 0;
range.e.cursor = chip_info.num_pips; range.e.cursor = chip_info.num_pips;
return range; return range;
} }
WireId getPipSrcWire(PipId pip) const WireId getPipSrcWire(PipId pip) const
{ {
WireId wire; WireId wire;
assert(!pip.nil()); assert(!pip.nil());
wire.index = chip_info.pip_data[pip.index].src; wire.index = chip_info.pip_data[pip.index].src;
return wire; return wire;
} }
WireId getPipDstWire(PipId pip) const WireId getPipDstWire(PipId pip) const
{ {
WireId wire; WireId wire;
assert(!pip.nil()); assert(!pip.nil());
wire.index = chip_info.pip_data[pip.index].dst; wire.index = chip_info.pip_data[pip.index].dst;
return wire; return wire;
} }
DelayInfo getPipDelay(PipId pip) const DelayInfo getPipDelay(PipId pip) const
{ {
DelayInfo delay; DelayInfo delay;
assert(!pip.nil()); assert(!pip.nil());
delay.delay = chip_info.pip_data[pip.index].delay; delay.delay = chip_info.pip_data[pip.index].delay;
return delay; return delay;
} }
PipRange getPipsDownhill(WireId wire) const PipRange getPipsDownhill(WireId wire) const
{ {
PipRange range; PipRange range;
assert(!wire.nil()); assert(!wire.nil());
range.b.cursor = chip_info.wire_data[wire.index].pips_downhill; range.b.cursor = chip_info.wire_data[wire.index].pips_downhill;
range.e.cursor = range.b.cursor + chip_info.wire_data[wire.index].num_downhill; range.e.cursor =
return range; range.b.cursor + chip_info.wire_data[wire.index].num_downhill;
} return range;
}
PipRange getPipsUphill(WireId wire) const PipRange getPipsUphill(WireId wire) const
{ {
PipRange range; PipRange range;
assert(!wire.nil()); assert(!wire.nil());
range.b.cursor = chip_info.wire_data[wire.index].pips_uphill; range.b.cursor = chip_info.wire_data[wire.index].pips_uphill;
range.e.cursor = range.b.cursor + chip_info.wire_data[wire.index].num_uphill; range.e.cursor =
return range; range.b.cursor + chip_info.wire_data[wire.index].num_uphill;
} return range;
}
PipRange getWireAliases(WireId wire) const PipRange getWireAliases(WireId wire) const
{ {
PipRange range; PipRange range;
assert(!wire.nil()); assert(!wire.nil());
range.b.cursor = nullptr; range.b.cursor = nullptr;
range.e.cursor = nullptr; range.e.cursor = nullptr;
return range; return range;
} }
// ------------------------------------------------- // -------------------------------------------------
void getBelPosition(BelId bel, float &x, float &y) const; void getBelPosition(BelId bel, float &x, float &y) const;
void getWirePosition(WireId wire, float &x, float &y) const; void getWirePosition(WireId wire, float &x, float &y) const;
void getPipPosition(PipId pip, float &x, float &y) const; void getPipPosition(PipId pip, float &x, float &y) const;
vector<GraphicElement> getBelGraphics(BelId bel) const; vector<GraphicElement> getBelGraphics(BelId bel) const;
vector<GraphicElement> getWireGraphics(WireId wire) const; vector<GraphicElement> getWireGraphics(WireId wire) const;
vector<GraphicElement> getPipGraphics(PipId pip) const; vector<GraphicElement> getPipGraphics(PipId pip) const;
vector<GraphicElement> getFrameGraphics() const; vector<GraphicElement> getFrameGraphics() const;
}; };
#endif #endif

View File

@ -1,4 +1,12 @@
set(devices 384 1k 5k 8k) if(ICE40_HX1K_ONLY)
set(devices 1k)
foreach (target ${family_targets})
target_compile_definitions(${target} PRIVATE ICE40_HX1K_ONLY=1)
endforeach (target)
else()
set(devices 384 1k 5k 8k)
endif()
set(DB_PY ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdb.py) set(DB_PY ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdb.py)
file(MAKE_DIRECTORY ice40/chipdbs/) file(MAKE_DIRECTORY ice40/chipdbs/)
add_library(ice40_chipdb OBJECT ice40/chipdbs/) add_library(ice40_chipdb OBJECT ice40/chipdbs/)

View File

@ -16,208 +16,244 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* *
*/ */
#include "design.h"
#include "mainwindow.h"
#include <QApplication> #include <QApplication>
#include <iostream>
#include <fstream>
#include "version.h"
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include "pybindings.h" #include <fstream>
#include <iostream>
#include "design.h"
#include "jsonparse.h" #include "jsonparse.h"
#include "mainwindow.h"
#include "pybindings.h"
#include "version.h"
void svg_dump_el(const GraphicElement &el) void svg_dump_el(const GraphicElement &el)
{ {
float scale = 10.0, offset = 10.0; float scale = 10.0, offset = 10.0;
std::string style = "stroke=\"black\" stroke-width=\"0.1\" fill=\"none\""; std::string style = "stroke=\"black\" stroke-width=\"0.1\" fill=\"none\"";
if (el.type == GraphicElement::G_BOX) { if (el.type == GraphicElement::G_BOX) {
std::cout << "<rect x=\"" << (offset + scale*el.x1) << "\" y=\"" << (offset + scale*el.y1) << std::cout << "<rect x=\"" << (offset + scale * el.x1) << "\" y=\""
"\" height=\"" << (scale*(el.y2-el.y1)) << "\" width=\"" << (scale*(el.x2-el.x1)) << "\" " << style << "/>\n"; << (offset + scale * el.y1) << "\" height=\""
} << (scale * (el.y2 - el.y1)) << "\" width=\""
<< (scale * (el.x2 - el.x1)) << "\" " << style << "/>\n";
}
if (el.type == GraphicElement::G_LINE) { if (el.type == GraphicElement::G_LINE) {
std::cout << "<line x1=\"" << (offset + scale*el.x1) << "\" y1=\"" << (offset + scale*el.y1) << std::cout << "<line x1=\"" << (offset + scale * el.x1) << "\" y1=\""
"\" x2=\"" << (offset + scale*el.x2) << "\" y2=\"" << (offset + scale*el.y2) << "\" " << style << "/>\n"; << (offset + scale * el.y1) << "\" x2=\""
} << (offset + scale * el.x2) << "\" y2=\""
<< (offset + scale * el.y2) << "\" " << style << "/>\n";
}
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
namespace po = boost::program_options; namespace po = boost::program_options;
int rc = 0;
std::string str;
std::string str; po::options_description options("Allowed options");
options.add_options()("help,h", "show help");
options.add_options()("test", "just a check");
options.add_options()("gui", "start gui");
options.add_options()("svg", "dump SVG file");
options.add_options()("run", po::value<std::vector<std::string>>(),
"python file to execute");
options.add_options()("json", po::value<std::string>(),
"JSON design file to ingest");
options.add_options()("version,v", "show version");
options.add_options()("lp384", "set device type to iCE40LP384");
options.add_options()("lp1k", "set device type to iCE40LP1K");
options.add_options()("lp8k", "set device type to iCE40LP8K");
options.add_options()("hx1k", "set device type to iCE40HX1K");
options.add_options()("hx8k", "set device type to iCE40HX8K");
options.add_options()("up5k", "set device type to iCE40UP5K");
po::options_description options("Allowed options"); po::positional_options_description pos;
options.add_options()("help,h","show help"); pos.add("run", -1);
options.add_options()("test","just a check");
options.add_options()("gui","start gui");
options.add_options()("svg","dump SVG file");
options.add_options()("file", po::value<std::string>(), "python file to execute");
options.add_options()("json", po::value<std::string>(), "JSON design file to ingest");
options.add_options()("version,v","show version");
options.add_options()("lp384","set device type to iCE40LP384");
options.add_options()("lp1k","set device type to iCE40LP1K");
options.add_options()("lp8k","set device type to iCE40LP8K");
options.add_options()("hx1k","set device type to iCE40HX1K");
options.add_options()("hx8k","set device type to iCE40HX8K");
options.add_options()("up5k","set device type to iCE40UP5K");
po::positional_options_description pos; po::variables_map vm;
pos.add("file", -1); try {
po::parsed_options parsed = po::command_line_parser(argc, argv)
.options(options)
.positional(pos)
.run();
po::variables_map vm; po::store(parsed, vm);
try {
po::parsed_options parsed = po::command_line_parser(argc, argv).
options(options).
positional(pos).
run();
po::store(parsed, vm); po::notify(vm);
}
po::notify(vm);
}
catch(std::exception& e) catch (std::exception &e) {
{ std::cout << e.what() << "\n";
std::cout << e.what() << "\n"; return 1;
return 1; }
}
if (vm.count("help") || argc == 1) if (vm.count("help") || argc == 1) {
{ help:
std::cout << basename(argv[0]) << " -- Next Generation Place and Route (git sha1 " GIT_COMMIT_HASH_STR ")\n"; std::cout << basename(argv[0])
std::cout << "\n"; << " -- Next Generation Place and Route (git "
std::cout << options << "\n"; "sha1 " GIT_COMMIT_HASH_STR ")\n";
return 1; std::cout << "\n";
} std::cout << options << "\n";
return argc != 1;
if (vm.count("version")) }
{
std::cout << basename(argv[0])
<< " -- Next Generation Place and Route (git sha1 "
GIT_COMMIT_HASH_STR ")\n";
return 1;
}
ChipArgs chipArgs; if (vm.count("version")) {
chipArgs.type = ChipArgs::HX1K; std::cout << basename(argv[0])
<< " -- Next Generation Place and Route (git "
"sha1 " GIT_COMMIT_HASH_STR ")\n";
return 1;
}
if (vm.count("lp384")) ChipArgs chipArgs;
chipArgs.type = ChipArgs::LP384;
if (vm.count("lp1k")) if (vm.count("lp384")) {
chipArgs.type = ChipArgs::LP1K; if (chipArgs.type != ChipArgs::NONE)
goto help;
chipArgs.type = ChipArgs::LP384;
}
if (vm.count("lp8k")) if (vm.count("lp1k")) {
chipArgs.type = ChipArgs::LP8K; if (chipArgs.type != ChipArgs::NONE)
goto help;
chipArgs.type = ChipArgs::LP1K;
}
if (vm.count("hx1k")) if (vm.count("lp8k")) {
chipArgs.type = ChipArgs::HX1K; if (chipArgs.type != ChipArgs::NONE)
goto help;
chipArgs.type = ChipArgs::LP8K;
}
if (vm.count("hx8k")) if (vm.count("hx1k")) {
chipArgs.type = ChipArgs::HX8K; if (chipArgs.type != ChipArgs::NONE)
goto help;
chipArgs.type = ChipArgs::HX1K;
}
if (vm.count("up5k")) if (vm.count("hx8k")) {
chipArgs.type = ChipArgs::UP5K; if (chipArgs.type != ChipArgs::NONE)
goto help;
chipArgs.type = ChipArgs::HX8K;
}
Design design(chipArgs); if (vm.count("up5k")) {
if (chipArgs.type != ChipArgs::NONE)
goto help;
chipArgs.type = ChipArgs::UP5K;
}
if (vm.count("gui")) if (chipArgs.type == ChipArgs::NONE)
{ chipArgs.type = ChipArgs::HX1K;
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec(); #ifdef ICE40_HX1K_ONLY
} if (chipArgs.type != ChipArgs::HX1K) {
std::cout << "This version of nextpnr-ice40 is built with HX1K-support "
"only.\n";
return 1;
}
#endif
if (vm.count("test")) Design design(chipArgs);
{ init_python(argv[0]);
int bel_count = 0, wire_count = 0, pip_count = 0; python_export_global("design", design);
std::cout << "Checking bel names.\n"; if (vm.count("test")) {
for (auto bel : design.chip.getBels()) { int bel_count = 0, wire_count = 0, pip_count = 0;
auto name = design.chip.getBelName(bel);
assert(bel == design.chip.getBelByName(name));
bel_count++;
}
std::cout << " checked " << bel_count << " bels.\n";
std::cout << "Checking wire names.\n"; std::cout << "Checking bel names.\n";
for (auto wire : design.chip.getWires()) { for (auto bel : design.chip.getBels()) {
auto name = design.chip.getWireName(wire); auto name = design.chip.getBelName(bel);
assert(wire == design.chip.getWireByName(name)); assert(bel == design.chip.getBelByName(name));
wire_count++; bel_count++;
} }
std::cout << " checked " << wire_count << " wires.\n"; std::cout << " checked " << bel_count << " bels.\n";
std::cout << "Checking pip names.\n"; std::cout << "Checking wire names.\n";
for (auto pip : design.chip.getPips()) { for (auto wire : design.chip.getWires()) {
auto name = design.chip.getPipName(pip); auto name = design.chip.getWireName(wire);
assert(pip == design.chip.getPipByName(name)); assert(wire == design.chip.getWireByName(name));
pip_count++; wire_count++;
} }
std::cout << " checked " << pip_count << " pips.\n"; std::cout << " checked " << wire_count << " wires.\n";
std::cout << "Checking uphill -> downhill consistency.\n"; std::cout << "Checking pip names.\n";
for (auto dst : design.chip.getWires()) { for (auto pip : design.chip.getPips()) {
for (auto uphill_pip : design.chip.getPipsUphill(dst)) { auto name = design.chip.getPipName(pip);
bool found_downhill = false; assert(pip == design.chip.getPipByName(name));
for (auto downhill_pip : design.chip.getPipsDownhill(design.chip.getPipSrcWire(uphill_pip))) { pip_count++;
if (uphill_pip == downhill_pip) { }
assert(!found_downhill); std::cout << " checked " << pip_count << " pips.\n";
found_downhill = true;
}
}
assert(found_downhill);
}
}
std::cout << "Checking downhill -> uphill consistency.\n"; std::cout << "Checking uphill -> downhill consistency.\n";
for (auto dst : design.chip.getWires()) { for (auto dst : design.chip.getWires()) {
for (auto downhill_pip : design.chip.getPipsDownhill(dst)) { for (auto uphill_pip : design.chip.getPipsUphill(dst)) {
bool found_uphill = false; bool found_downhill = false;
for (auto uphill_pip : design.chip.getPipsUphill(design.chip.getPipDstWire(downhill_pip))) { for (auto downhill_pip : design.chip.getPipsDownhill(
if (uphill_pip == downhill_pip) { design.chip.getPipSrcWire(uphill_pip))) {
assert(!found_uphill); if (uphill_pip == downhill_pip) {
found_uphill = true; assert(!found_downhill);
} found_downhill = true;
} }
assert(found_uphill); }
} assert(found_downhill);
} }
}
return 0; std::cout << "Checking downhill -> uphill consistency.\n";
} for (auto dst : design.chip.getWires()) {
for (auto downhill_pip : design.chip.getPipsDownhill(dst)) {
bool found_uphill = false;
for (auto uphill_pip : design.chip.getPipsUphill(
design.chip.getPipDstWire(downhill_pip))) {
if (uphill_pip == downhill_pip) {
assert(!found_uphill);
found_uphill = true;
}
}
assert(found_uphill);
}
}
if (vm.count("svg")) return 0;
{ }
std::cout << "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
for (auto bel : design.chip.getBels()) {
std::cout << "<!-- " << design.chip.getBelName(bel) << " -->\n";
for (auto &el : design.chip.getBelGraphics(bel))
svg_dump_el(el);
}
std::cout << "<!-- Frame -->\n";
for (auto &el : design.chip.getFrameGraphics())
svg_dump_el(el);
std::cout << "</svg>\n";
}
if (vm.count("json")) if (vm.count("svg")) {
{ std::cout << "<svg xmlns=\"http://www.w3.org/2000/svg\" "
std::string filename = vm["json"].as<std::string>(); "xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
std::istream *f = new std::ifstream(filename); for (auto bel : design.chip.getBels()) {
std::cout << "<!-- " << design.chip.getBelName(bel) << " -->\n";
parse_json_file(f, filename, &design); for (auto &el : design.chip.getBelGraphics(bel))
} svg_dump_el(el);
}
if (vm.count("file")) std::cout << "<!-- Frame -->\n";
{ for (auto &el : design.chip.getFrameGraphics())
std::string filename = vm["file"].as<std::string>(); svg_dump_el(el);
execute_python_file(argv[0],filename.c_str()); std::cout << "</svg>\n";
} }
return 0; if (vm.count("json")) {
std::string filename = vm["json"].as<std::string>();
std::istream *f = new std::ifstream(filename);
parse_json_file(f, filename, &design);
}
if (vm.count("run")) {
std::vector<std::string> files =
vm["run"].as<std::vector<std::string>>();
for (auto filename : files)
execute_python_file(filename.c_str());
}
if (vm.count("gui")) {
QApplication a(argc, argv);
MainWindow w;
w.show();
rc = a.exec();
}
deinit_python();
return rc;
} }

View File

@ -18,13 +18,15 @@
* *
*/ */
#include "design.h"
#include "chip.h" #include "chip.h"
#include "design.h"
// include after design.h/chip.h
#include "pybindings.h" #include "pybindings.h"
void arch_wrap_python() { void arch_wrap_python()
class_<ChipArgs>("ChipArgs") {
.def_readwrite("type", &ChipArgs::type); class_<ChipArgs>("ChipArgs").def_readwrite("type", &ChipArgs::type);
enum_<decltype(std::declval<ChipArgs>().type)>("iCE40Type") enum_<decltype(std::declval<ChipArgs>().type)>("iCE40Type")
.value("NONE", ChipArgs::NONE) .value("NONE", ChipArgs::NONE)

6
python/dump_design.py Normal file
View File

@ -0,0 +1,6 @@
# Run ./nextpnr-ice40 --json ice40/blinky.json --run python/dump_design.py
for cell in sorted(design.cells, key=lambda x: x.first):
print("Cell {} : {}".format(cell.first, cell.second.type))
for port in sorted(cell.second.ports, key=lambda x: x.first):
dir = (" <-- ", " --> ", " <-> ")[int(port.second.type)]
print(" {} {} {}".format(port.first, dir, port.second.net.name))

2
python/functions.py Normal file
View File

@ -0,0 +1,2 @@
def test_function():
print("Hello World!")