Merge branch 'master' into gqtech
This commit is contained in:
commit
1ed5c641c1
@ -47,12 +47,10 @@ DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
- Regex: '^(<|"(gtest|isl|json)/)'
|
||||
Priority: 3
|
||||
- Regex: '.*'
|
||||
- Regex: '<.*>'
|
||||
Priority: 1
|
||||
- Regex: '.*'
|
||||
Priority: 2
|
||||
IndentCaseLabels: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -18,3 +18,4 @@ CMakeCache.txt
|
||||
.*.swp
|
||||
a.out
|
||||
*.json
|
||||
build/
|
||||
|
@ -21,6 +21,7 @@ Building
|
||||
|
||||
- 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 with HX1K support only, run ` cmake -DCMAKE_BUILD_TYPE=Debug -DICE40_HX1K_ONLY=1 .`
|
||||
- For a release build, run `cmake .`
|
||||
- Use Make to run the build itself
|
||||
- For all targets, just run `make`
|
||||
|
@ -18,4 +18,3 @@
|
||||
*/
|
||||
|
||||
#include "design.h"
|
||||
|
||||
|
115
common/design.h
115
common/design.h
@ -20,50 +20,52 @@
|
||||
#ifndef DESIGN_H
|
||||
#define DESIGN_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
// replace with proper IdString later
|
||||
typedef std::string IdString;
|
||||
|
||||
// replace with haslib later
|
||||
template<typename T> using pool = std::unordered_set<T>;
|
||||
template<typename T, typename U> using dict = std::unordered_map<T, U>;
|
||||
template <typename T> using pool = std::unordered_set<T>;
|
||||
template <typename T, typename U> using dict = std::unordered_map<T, U>;
|
||||
using std::vector;
|
||||
|
||||
struct GraphicElement
|
||||
{
|
||||
// This will control colour, and there should be separate
|
||||
// visibility controls in some cases also
|
||||
enum {
|
||||
// Wires entirely inside tiles, e.g. between switchbox and bels
|
||||
G_LOCAL_WIRES,
|
||||
// Standard inter-tile routing
|
||||
G_GENERAL_WIRES,
|
||||
// Special inter-tile wires, e.g. carry chains
|
||||
G_DEDICATED_WIRES,
|
||||
G_BEL_OUTLINE,
|
||||
G_SWITCHBOX_OUTLINE,
|
||||
G_TILE_OUTLINE,
|
||||
G_BEL_PINS,
|
||||
G_SWITCHBOX_PINS,
|
||||
G_BEL_MISC,
|
||||
G_TILE_MISC,
|
||||
} style;
|
||||
// This will control colour, and there should be separate
|
||||
// visibility controls in some cases also
|
||||
enum
|
||||
{
|
||||
// Wires entirely inside tiles, e.g. between switchbox and bels
|
||||
G_LOCAL_WIRES,
|
||||
// Standard inter-tile routing
|
||||
G_GENERAL_WIRES,
|
||||
// Special inter-tile wires, e.g. carry chains
|
||||
G_DEDICATED_WIRES,
|
||||
G_BEL_OUTLINE,
|
||||
G_SWITCHBOX_OUTLINE,
|
||||
G_TILE_OUTLINE,
|
||||
G_BEL_PINS,
|
||||
G_SWITCHBOX_PINS,
|
||||
G_BEL_MISC,
|
||||
G_TILE_MISC,
|
||||
} style;
|
||||
|
||||
enum {
|
||||
G_LINE,
|
||||
G_BOX,
|
||||
G_CIRCLE,
|
||||
G_LABEL
|
||||
} type;
|
||||
enum
|
||||
{
|
||||
G_LINE,
|
||||
G_BOX,
|
||||
G_CIRCLE,
|
||||
G_LABEL
|
||||
} type;
|
||||
|
||||
float x1, y1, x2, y2, z;
|
||||
std::string text;
|
||||
float x1, y1, x2, y2, z;
|
||||
std::string text;
|
||||
};
|
||||
|
||||
#include "chip.h"
|
||||
@ -72,56 +74,57 @@ struct CellInfo;
|
||||
|
||||
struct PortRef
|
||||
{
|
||||
CellInfo *cell;
|
||||
IdString port;
|
||||
CellInfo *cell;
|
||||
IdString port;
|
||||
};
|
||||
|
||||
struct NetInfo
|
||||
{
|
||||
IdString name;
|
||||
PortRef driver;
|
||||
vector<PortRef> users;
|
||||
dict<IdString, std::string> attrs;
|
||||
IdString name;
|
||||
PortRef driver;
|
||||
vector<PortRef> users;
|
||||
dict<IdString, std::string> attrs;
|
||||
|
||||
// wire -> (uphill_wire, delay)
|
||||
dict<WireId, std::pair<WireId, DelayInfo>> wires;
|
||||
// wire -> (uphill_wire, delay)
|
||||
dict<WireId, std::pair<WireId, DelayInfo>> wires;
|
||||
};
|
||||
|
||||
enum PortType
|
||||
{
|
||||
PORT_IN = 0,
|
||||
PORT_OUT = 1,
|
||||
PORT_INOUT = 2
|
||||
PORT_IN = 0,
|
||||
PORT_OUT = 1,
|
||||
PORT_INOUT = 2
|
||||
};
|
||||
|
||||
struct PortInfo
|
||||
{
|
||||
IdString name;
|
||||
NetInfo *net;
|
||||
PortType type;
|
||||
IdString name;
|
||||
NetInfo *net;
|
||||
PortType type;
|
||||
};
|
||||
|
||||
struct CellInfo
|
||||
{
|
||||
IdString name, type;
|
||||
dict<IdString, PortInfo> ports;
|
||||
dict<IdString, std::string> attrs, params;
|
||||
IdString name, type;
|
||||
dict<IdString, PortInfo> ports;
|
||||
dict<IdString, std::string> attrs, params;
|
||||
|
||||
BelId bel;
|
||||
// cell_port -> bel_pin
|
||||
dict<IdString, IdString> pins;
|
||||
BelId bel;
|
||||
// cell_port -> bel_pin
|
||||
dict<IdString, IdString> pins;
|
||||
};
|
||||
|
||||
struct Design
|
||||
{
|
||||
struct Chip chip;
|
||||
struct Chip chip;
|
||||
|
||||
Design(ChipArgs args) : chip(args) {
|
||||
// ...
|
||||
}
|
||||
Design(ChipArgs args) : chip(args)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
dict<IdString, NetInfo*> nets;
|
||||
dict<IdString, CellInfo*> cells;
|
||||
dict<IdString, NetInfo *> nets;
|
||||
dict<IdString, CellInfo *> cells;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -18,24 +18,89 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "design.h"
|
||||
#include "chip.h"
|
||||
#include "design.h"
|
||||
#include "emb.h"
|
||||
|
||||
// include after design.h/chip.h
|
||||
#include "pybindings.h"
|
||||
|
||||
// Required to determine concatenated module name (which differs for different archs)
|
||||
#define PASTER(x, y) x ## _ ## y
|
||||
#define EVALUATOR(x, y) PASTER(x,y)
|
||||
// Required to determine concatenated module name (which differs for different
|
||||
// archs)
|
||||
#define PASTER(x, y) x##_##y
|
||||
#define EVALUATOR(x, y) PASTER(x, y)
|
||||
#define MODULE_NAME EVALUATOR(nextpnrpy, ARCHNAME)
|
||||
#define PYINIT_MODULE_NAME EVALUATOR(&PyInit_nextpnrpy, ARCHNAME)
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
|
||||
// Architecture-specific bindings should be created in the below function, which must be implemented in all
|
||||
// architectures
|
||||
// Architecture-specific bindings should be created in the below function, which
|
||||
// must be implemented in all architectures
|
||||
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();
|
||||
}
|
||||
|
||||
@ -44,35 +109,47 @@ void arch_appendinittab()
|
||||
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) {
|
||||
fprintf(stderr, "Fatal error: cannot decode executable filename\n");
|
||||
exit(1);
|
||||
}
|
||||
try
|
||||
{
|
||||
try {
|
||||
PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME);
|
||||
emb::append_inittab();
|
||||
Py_SetProgramName(program);
|
||||
Py_Initialize();
|
||||
|
||||
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);
|
||||
|
||||
Py_Finalize();
|
||||
PyMem_RawFree(program);
|
||||
}
|
||||
catch(boost::python::error_already_set const &)
|
||||
{
|
||||
PyImport_ImportModule(TOSTRING(MODULE_NAME));
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -20,67 +20,98 @@
|
||||
|
||||
#ifndef COMMON_PYBINDINGS_H
|
||||
#define COMMON_PYBINDINGS_H
|
||||
#include <utility>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "pycontainers.h"
|
||||
|
||||
#include <Python.h>
|
||||
#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/map_indexing_suite.hpp>
|
||||
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
using namespace boost::python;
|
||||
|
||||
/*
|
||||
A wrapper for a Pythonised nextpnr Iterator. The actual class wrapped is a
|
||||
pair<Iterator, Iterator> containing (current, end)
|
||||
*/
|
||||
A wrapper to enable custom type/ID to/from string conversions
|
||||
*/
|
||||
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>
|
||||
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 *convertible(PyObject *object)
|
||||
{
|
||||
return PyUnicode_Check(object) ? object : 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void wrap(const char *python_name) {
|
||||
class_<std::pair<T, T>>(python_name, no_init)
|
||||
.def("__next__", next);
|
||||
}
|
||||
static void construct(PyObject *object,
|
||||
converter::rvalue_from_python_stage1_data *data)
|
||||
{
|
||||
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();
|
||||
|
||||
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();
|
||||
|
||||
#endif /* end of include guard: COMMON_PYBINDINGS_HH */
|
||||
|
129
common/pycontainers.h
Normal file
129
common/pycontainers.h
Normal 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
|
@ -57,5 +57,6 @@ bool check_all_nets_driven(Design *design) {
|
||||
}
|
||||
|
||||
if (debug) log_info(" Verified!\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,4 @@
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
Chip::Chip(ChipArgs)
|
||||
{
|
||||
}
|
||||
Chip::Chip(ChipArgs) {}
|
||||
|
84
dummy/chip.h
84
dummy/chip.h
@ -24,10 +24,10 @@
|
||||
|
||||
struct DelayInfo
|
||||
{
|
||||
float delay = 0;
|
||||
float delay = 0;
|
||||
|
||||
float raiseDelay() { return delay; }
|
||||
float fallDelay() { return delay; }
|
||||
float raiseDelay() { return delay; }
|
||||
float fallDelay() { return delay; }
|
||||
};
|
||||
|
||||
typedef IdString BelType;
|
||||
@ -45,8 +45,8 @@ typedef IdString PipId;
|
||||
|
||||
struct BelPin
|
||||
{
|
||||
BelId bel;
|
||||
PortPin pin;
|
||||
BelId bel;
|
||||
PortPin pin;
|
||||
};
|
||||
|
||||
struct ChipArgs
|
||||
@ -55,48 +55,48 @@ struct ChipArgs
|
||||
|
||||
struct Chip
|
||||
{
|
||||
Chip(ChipArgs args);
|
||||
Chip(ChipArgs args);
|
||||
|
||||
BelId getBelByName(IdString name) const;
|
||||
BelId getBelByName(IdString name) const;
|
||||
|
||||
IdString getBelName(BelId bel) const;
|
||||
void bindBel(BelId bel, IdString cell);
|
||||
void unbindBel(BelId bel);
|
||||
bool checkBelAvail(BelId bel) const;
|
||||
const vector<BelId> &getBels() const;
|
||||
const vector<BelId> &getBelsByType(BelType type) const;
|
||||
BelType getBelType(BelId bel) const;
|
||||
WireId getWireBelPin(BelId bel, PortPin pin) const;
|
||||
BelPin getBelPinUphill(WireId wire) const;
|
||||
const vector<BelPin> &getBelPinsDownhill(WireId wire) const;
|
||||
IdString getBelName(BelId bel) const;
|
||||
void bindBel(BelId bel, IdString cell);
|
||||
void unbindBel(BelId bel);
|
||||
bool checkBelAvail(BelId bel) const;
|
||||
const vector<BelId> &getBels() const;
|
||||
const vector<BelId> &getBelsByType(BelType type) const;
|
||||
BelType getBelType(BelId bel) const;
|
||||
WireId getWireBelPin(BelId bel, PortPin pin) const;
|
||||
BelPin getBelPinUphill(WireId wire) const;
|
||||
const vector<BelPin> &getBelPinsDownhill(WireId wire) const;
|
||||
|
||||
WireId getWireByName(IdString name) const;
|
||||
IdString getWireName(WireId wire) const;
|
||||
void bindWire(WireId bel, IdString net);
|
||||
void unbindWire(WireId bel);
|
||||
bool checkWireAvail(WireId bel) const;
|
||||
const vector<WireId> &getWires() const;
|
||||
WireId getWireByName(IdString name) const;
|
||||
IdString getWireName(WireId wire) const;
|
||||
void bindWire(WireId bel, IdString net);
|
||||
void unbindWire(WireId bel);
|
||||
bool checkWireAvail(WireId bel) const;
|
||||
const vector<WireId> &getWires() const;
|
||||
|
||||
PipId getPipByName(IdString name) const;
|
||||
IdString getPipName(PipId pip) const;
|
||||
void bindPip(PipId bel, IdString net);
|
||||
void unbindPip(PipId bel);
|
||||
bool checkPipAvail(PipId bel) const;
|
||||
const vector<PipId> &getPips() const;
|
||||
WireId getPipSrcWire(PipId pip) const;
|
||||
WireId getPipDstWire(PipId pip) const;
|
||||
DelayInfo getPipDelay(PipId pip) const;
|
||||
const vector<PipId> &getPipsDownhill(WireId wire) const;
|
||||
const vector<PipId> &getPipsUphill(WireId wire) const;
|
||||
const vector<PipId> &getWireAliases(WireId wire) const;
|
||||
PipId getPipByName(IdString name) const;
|
||||
IdString getPipName(PipId pip) const;
|
||||
void bindPip(PipId bel, IdString net);
|
||||
void unbindPip(PipId bel);
|
||||
bool checkPipAvail(PipId bel) const;
|
||||
const vector<PipId> &getPips() const;
|
||||
WireId getPipSrcWire(PipId pip) const;
|
||||
WireId getPipDstWire(PipId pip) const;
|
||||
DelayInfo getPipDelay(PipId pip) const;
|
||||
const vector<PipId> &getPipsDownhill(WireId wire) const;
|
||||
const vector<PipId> &getPipsUphill(WireId wire) const;
|
||||
const vector<PipId> &getWireAliases(WireId wire) const;
|
||||
|
||||
void getBelPosition(BelId bel, float &x, float &y) const;
|
||||
void getWirePosition(WireId wire, float &x, float &y) const;
|
||||
void getPipPosition(PipId pip, float &x, float &y) const;
|
||||
vector<GraphicElement> getBelGraphics(BelId bel) const;
|
||||
vector<GraphicElement> getWireGraphics(WireId wire) const;
|
||||
vector<GraphicElement> getPipGraphics(PipId pip) const;
|
||||
vector<GraphicElement> getFrameGraphics() const;
|
||||
void getBelPosition(BelId bel, float &x, float &y) const;
|
||||
void getWirePosition(WireId wire, float &x, float &y) const;
|
||||
void getPipPosition(PipId pip, float &x, float &y) const;
|
||||
vector<GraphicElement> getBelGraphics(BelId bel) const;
|
||||
vector<GraphicElement> getWireGraphics(WireId wire) const;
|
||||
vector<GraphicElement> getPipGraphics(PipId pip) const;
|
||||
vector<GraphicElement> getFrameGraphics() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -17,15 +17,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include "design.h"
|
||||
#include "mainwindow.h"
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Design design(ChipArgs{});
|
||||
Design design(ChipArgs{});
|
||||
|
||||
QApplication a(argc, argv);
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
||||
|
@ -18,10 +18,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "design.h"
|
||||
#include "chip.h"
|
||||
#include "design.h"
|
||||
|
||||
// include after design.h/chip.h
|
||||
#include "pybindings.h"
|
||||
|
||||
void arch_wrap_python() {
|
||||
class_<ChipArgs>("ChipArgs");
|
||||
}
|
||||
void arch_wrap_python() { class_<ChipArgs>("ChipArgs"); }
|
||||
|
@ -11,9 +11,6 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
emb::append_inittab();
|
||||
arch_appendinittab();
|
||||
Py_Initialize();
|
||||
PyImport_ImportModule("emb");
|
||||
|
||||
write = [this] (std::string s) {
|
||||
@ -27,7 +24,6 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
Py_Finalize();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
700
ice40/chip.cc
700
ice40/chip.cc
@ -23,460 +23,470 @@
|
||||
|
||||
IdString belTypeToId(BelType type)
|
||||
{
|
||||
if (type == TYPE_ICESTORM_LC)
|
||||
return "ICESTORM_LC";
|
||||
if (type == TYPE_ICESTORM_RAM)
|
||||
return "ICESTORM_RAM";
|
||||
if (type == TYPE_SB_IO)
|
||||
return "SB_IO";
|
||||
return IdString();
|
||||
if (type == TYPE_ICESTORM_LC)
|
||||
return "ICESTORM_LC";
|
||||
if (type == TYPE_ICESTORM_RAM)
|
||||
return "ICESTORM_RAM";
|
||||
if (type == TYPE_SB_IO)
|
||||
return "SB_IO";
|
||||
return IdString();
|
||||
}
|
||||
|
||||
BelType belTypeFromId(IdString id)
|
||||
{
|
||||
if (id == "ICESTORM_LC")
|
||||
return TYPE_ICESTORM_LC;
|
||||
if (id == "ICESTORM_RAM")
|
||||
return TYPE_ICESTORM_RAM;
|
||||
if (id == "SB_IO")
|
||||
return TYPE_SB_IO;
|
||||
return TYPE_NIL;
|
||||
if (id == "ICESTORM_LC")
|
||||
return TYPE_ICESTORM_LC;
|
||||
if (id == "ICESTORM_RAM")
|
||||
return TYPE_ICESTORM_RAM;
|
||||
if (id == "SB_IO")
|
||||
return TYPE_SB_IO;
|
||||
return TYPE_NIL;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
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_1)
|
||||
X(IN_2)
|
||||
X(IN_3)
|
||||
X(O)
|
||||
X(LO)
|
||||
X(CIN)
|
||||
X(COUT)
|
||||
X(CEN)
|
||||
X(CLK)
|
||||
X(SR)
|
||||
X(IN_0)
|
||||
X(IN_1)
|
||||
X(IN_2)
|
||||
X(IN_3)
|
||||
X(O)
|
||||
X(LO)
|
||||
X(CIN)
|
||||
X(COUT)
|
||||
X(CEN)
|
||||
X(CLK)
|
||||
X(SR)
|
||||
|
||||
X(MASK_0)
|
||||
X(MASK_1)
|
||||
X(MASK_2)
|
||||
X(MASK_3)
|
||||
X(MASK_4)
|
||||
X(MASK_5)
|
||||
X(MASK_6)
|
||||
X(MASK_7)
|
||||
X(MASK_8)
|
||||
X(MASK_9)
|
||||
X(MASK_10)
|
||||
X(MASK_11)
|
||||
X(MASK_12)
|
||||
X(MASK_13)
|
||||
X(MASK_14)
|
||||
X(MASK_15)
|
||||
X(MASK_0)
|
||||
X(MASK_1)
|
||||
X(MASK_2)
|
||||
X(MASK_3)
|
||||
X(MASK_4)
|
||||
X(MASK_5)
|
||||
X(MASK_6)
|
||||
X(MASK_7)
|
||||
X(MASK_8)
|
||||
X(MASK_9)
|
||||
X(MASK_10)
|
||||
X(MASK_11)
|
||||
X(MASK_12)
|
||||
X(MASK_13)
|
||||
X(MASK_14)
|
||||
X(MASK_15)
|
||||
|
||||
X(RDATA_0)
|
||||
X(RDATA_1)
|
||||
X(RDATA_2)
|
||||
X(RDATA_3)
|
||||
X(RDATA_4)
|
||||
X(RDATA_5)
|
||||
X(RDATA_6)
|
||||
X(RDATA_7)
|
||||
X(RDATA_8)
|
||||
X(RDATA_9)
|
||||
X(RDATA_10)
|
||||
X(RDATA_11)
|
||||
X(RDATA_12)
|
||||
X(RDATA_13)
|
||||
X(RDATA_14)
|
||||
X(RDATA_15)
|
||||
X(RDATA_0)
|
||||
X(RDATA_1)
|
||||
X(RDATA_2)
|
||||
X(RDATA_3)
|
||||
X(RDATA_4)
|
||||
X(RDATA_5)
|
||||
X(RDATA_6)
|
||||
X(RDATA_7)
|
||||
X(RDATA_8)
|
||||
X(RDATA_9)
|
||||
X(RDATA_10)
|
||||
X(RDATA_11)
|
||||
X(RDATA_12)
|
||||
X(RDATA_13)
|
||||
X(RDATA_14)
|
||||
X(RDATA_15)
|
||||
|
||||
X(WDATA_0)
|
||||
X(WDATA_1)
|
||||
X(WDATA_2)
|
||||
X(WDATA_3)
|
||||
X(WDATA_4)
|
||||
X(WDATA_5)
|
||||
X(WDATA_6)
|
||||
X(WDATA_7)
|
||||
X(WDATA_8)
|
||||
X(WDATA_9)
|
||||
X(WDATA_10)
|
||||
X(WDATA_11)
|
||||
X(WDATA_12)
|
||||
X(WDATA_13)
|
||||
X(WDATA_14)
|
||||
X(WDATA_15)
|
||||
X(WDATA_0)
|
||||
X(WDATA_1)
|
||||
X(WDATA_2)
|
||||
X(WDATA_3)
|
||||
X(WDATA_4)
|
||||
X(WDATA_5)
|
||||
X(WDATA_6)
|
||||
X(WDATA_7)
|
||||
X(WDATA_8)
|
||||
X(WDATA_9)
|
||||
X(WDATA_10)
|
||||
X(WDATA_11)
|
||||
X(WDATA_12)
|
||||
X(WDATA_13)
|
||||
X(WDATA_14)
|
||||
X(WDATA_15)
|
||||
|
||||
X(WADDR_0)
|
||||
X(WADDR_1)
|
||||
X(WADDR_2)
|
||||
X(WADDR_3)
|
||||
X(WADDR_4)
|
||||
X(WADDR_5)
|
||||
X(WADDR_6)
|
||||
X(WADDR_7)
|
||||
X(WADDR_8)
|
||||
X(WADDR_9)
|
||||
X(WADDR_10)
|
||||
X(WADDR_0)
|
||||
X(WADDR_1)
|
||||
X(WADDR_2)
|
||||
X(WADDR_3)
|
||||
X(WADDR_4)
|
||||
X(WADDR_5)
|
||||
X(WADDR_6)
|
||||
X(WADDR_7)
|
||||
X(WADDR_8)
|
||||
X(WADDR_9)
|
||||
X(WADDR_10)
|
||||
|
||||
X(RADDR_0)
|
||||
X(RADDR_1)
|
||||
X(RADDR_2)
|
||||
X(RADDR_3)
|
||||
X(RADDR_4)
|
||||
X(RADDR_5)
|
||||
X(RADDR_6)
|
||||
X(RADDR_7)
|
||||
X(RADDR_8)
|
||||
X(RADDR_9)
|
||||
X(RADDR_10)
|
||||
X(RADDR_0)
|
||||
X(RADDR_1)
|
||||
X(RADDR_2)
|
||||
X(RADDR_3)
|
||||
X(RADDR_4)
|
||||
X(RADDR_5)
|
||||
X(RADDR_6)
|
||||
X(RADDR_7)
|
||||
X(RADDR_8)
|
||||
X(RADDR_9)
|
||||
X(RADDR_10)
|
||||
|
||||
X(WCLK)
|
||||
X(WCLKE)
|
||||
X(WE)
|
||||
X(WCLK)
|
||||
X(WCLKE)
|
||||
X(WE)
|
||||
|
||||
X(RCLK)
|
||||
X(RCLKE)
|
||||
X(RE)
|
||||
X(RCLK)
|
||||
X(RCLKE)
|
||||
X(RE)
|
||||
|
||||
X(PACKAGE_PIN)
|
||||
X(LATCH_INPUT_VALUE)
|
||||
X(CLOCK_ENABLE)
|
||||
X(INPUT_CLK)
|
||||
X(OUTPUT_CLK)
|
||||
X(OUTPUT_ENABLE)
|
||||
X(D_OUT_0)
|
||||
X(D_OUT_1)
|
||||
X(D_IN_0)
|
||||
X(D_IN_1)
|
||||
X(PACKAGE_PIN)
|
||||
X(LATCH_INPUT_VALUE)
|
||||
X(CLOCK_ENABLE)
|
||||
X(INPUT_CLK)
|
||||
X(OUTPUT_CLK)
|
||||
X(OUTPUT_ENABLE)
|
||||
X(D_OUT_0)
|
||||
X(D_OUT_1)
|
||||
X(D_IN_0)
|
||||
X(D_IN_1)
|
||||
|
||||
#undef X
|
||||
return IdString();
|
||||
return IdString();
|
||||
}
|
||||
|
||||
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_1)
|
||||
X(IN_2)
|
||||
X(IN_3)
|
||||
X(O)
|
||||
X(LO)
|
||||
X(CIN)
|
||||
X(COUT)
|
||||
X(CEN)
|
||||
X(CLK)
|
||||
X(SR)
|
||||
X(IN_0)
|
||||
X(IN_1)
|
||||
X(IN_2)
|
||||
X(IN_3)
|
||||
X(O)
|
||||
X(LO)
|
||||
X(CIN)
|
||||
X(COUT)
|
||||
X(CEN)
|
||||
X(CLK)
|
||||
X(SR)
|
||||
|
||||
X(MASK_0)
|
||||
X(MASK_1)
|
||||
X(MASK_2)
|
||||
X(MASK_3)
|
||||
X(MASK_4)
|
||||
X(MASK_5)
|
||||
X(MASK_6)
|
||||
X(MASK_7)
|
||||
X(MASK_8)
|
||||
X(MASK_9)
|
||||
X(MASK_10)
|
||||
X(MASK_11)
|
||||
X(MASK_12)
|
||||
X(MASK_13)
|
||||
X(MASK_14)
|
||||
X(MASK_15)
|
||||
X(MASK_0)
|
||||
X(MASK_1)
|
||||
X(MASK_2)
|
||||
X(MASK_3)
|
||||
X(MASK_4)
|
||||
X(MASK_5)
|
||||
X(MASK_6)
|
||||
X(MASK_7)
|
||||
X(MASK_8)
|
||||
X(MASK_9)
|
||||
X(MASK_10)
|
||||
X(MASK_11)
|
||||
X(MASK_12)
|
||||
X(MASK_13)
|
||||
X(MASK_14)
|
||||
X(MASK_15)
|
||||
|
||||
X(RDATA_0)
|
||||
X(RDATA_1)
|
||||
X(RDATA_2)
|
||||
X(RDATA_3)
|
||||
X(RDATA_4)
|
||||
X(RDATA_5)
|
||||
X(RDATA_6)
|
||||
X(RDATA_7)
|
||||
X(RDATA_8)
|
||||
X(RDATA_9)
|
||||
X(RDATA_10)
|
||||
X(RDATA_11)
|
||||
X(RDATA_12)
|
||||
X(RDATA_13)
|
||||
X(RDATA_14)
|
||||
X(RDATA_15)
|
||||
X(RDATA_0)
|
||||
X(RDATA_1)
|
||||
X(RDATA_2)
|
||||
X(RDATA_3)
|
||||
X(RDATA_4)
|
||||
X(RDATA_5)
|
||||
X(RDATA_6)
|
||||
X(RDATA_7)
|
||||
X(RDATA_8)
|
||||
X(RDATA_9)
|
||||
X(RDATA_10)
|
||||
X(RDATA_11)
|
||||
X(RDATA_12)
|
||||
X(RDATA_13)
|
||||
X(RDATA_14)
|
||||
X(RDATA_15)
|
||||
|
||||
X(WDATA_0)
|
||||
X(WDATA_1)
|
||||
X(WDATA_2)
|
||||
X(WDATA_3)
|
||||
X(WDATA_4)
|
||||
X(WDATA_5)
|
||||
X(WDATA_6)
|
||||
X(WDATA_7)
|
||||
X(WDATA_8)
|
||||
X(WDATA_9)
|
||||
X(WDATA_10)
|
||||
X(WDATA_11)
|
||||
X(WDATA_12)
|
||||
X(WDATA_13)
|
||||
X(WDATA_14)
|
||||
X(WDATA_15)
|
||||
X(WDATA_0)
|
||||
X(WDATA_1)
|
||||
X(WDATA_2)
|
||||
X(WDATA_3)
|
||||
X(WDATA_4)
|
||||
X(WDATA_5)
|
||||
X(WDATA_6)
|
||||
X(WDATA_7)
|
||||
X(WDATA_8)
|
||||
X(WDATA_9)
|
||||
X(WDATA_10)
|
||||
X(WDATA_11)
|
||||
X(WDATA_12)
|
||||
X(WDATA_13)
|
||||
X(WDATA_14)
|
||||
X(WDATA_15)
|
||||
|
||||
X(WADDR_0)
|
||||
X(WADDR_1)
|
||||
X(WADDR_2)
|
||||
X(WADDR_3)
|
||||
X(WADDR_4)
|
||||
X(WADDR_5)
|
||||
X(WADDR_6)
|
||||
X(WADDR_7)
|
||||
X(WADDR_8)
|
||||
X(WADDR_9)
|
||||
X(WADDR_10)
|
||||
X(WADDR_0)
|
||||
X(WADDR_1)
|
||||
X(WADDR_2)
|
||||
X(WADDR_3)
|
||||
X(WADDR_4)
|
||||
X(WADDR_5)
|
||||
X(WADDR_6)
|
||||
X(WADDR_7)
|
||||
X(WADDR_8)
|
||||
X(WADDR_9)
|
||||
X(WADDR_10)
|
||||
|
||||
X(RADDR_0)
|
||||
X(RADDR_1)
|
||||
X(RADDR_2)
|
||||
X(RADDR_3)
|
||||
X(RADDR_4)
|
||||
X(RADDR_5)
|
||||
X(RADDR_6)
|
||||
X(RADDR_7)
|
||||
X(RADDR_8)
|
||||
X(RADDR_9)
|
||||
X(RADDR_10)
|
||||
X(RADDR_0)
|
||||
X(RADDR_1)
|
||||
X(RADDR_2)
|
||||
X(RADDR_3)
|
||||
X(RADDR_4)
|
||||
X(RADDR_5)
|
||||
X(RADDR_6)
|
||||
X(RADDR_7)
|
||||
X(RADDR_8)
|
||||
X(RADDR_9)
|
||||
X(RADDR_10)
|
||||
|
||||
X(WCLK)
|
||||
X(WCLKE)
|
||||
X(WE)
|
||||
X(WCLK)
|
||||
X(WCLKE)
|
||||
X(WE)
|
||||
|
||||
X(RCLK)
|
||||
X(RCLKE)
|
||||
X(RE)
|
||||
X(RCLK)
|
||||
X(RCLKE)
|
||||
X(RE)
|
||||
|
||||
X(PACKAGE_PIN)
|
||||
X(LATCH_INPUT_VALUE)
|
||||
X(CLOCK_ENABLE)
|
||||
X(INPUT_CLK)
|
||||
X(OUTPUT_CLK)
|
||||
X(OUTPUT_ENABLE)
|
||||
X(D_OUT_0)
|
||||
X(D_OUT_1)
|
||||
X(D_IN_0)
|
||||
X(D_IN_1)
|
||||
X(PACKAGE_PIN)
|
||||
X(LATCH_INPUT_VALUE)
|
||||
X(CLOCK_ENABLE)
|
||||
X(INPUT_CLK)
|
||||
X(OUTPUT_CLK)
|
||||
X(OUTPUT_ENABLE)
|
||||
X(D_OUT_0)
|
||||
X(D_OUT_1)
|
||||
X(D_IN_0)
|
||||
X(D_IN_1)
|
||||
|
||||
#undef X
|
||||
return PIN_NIL;
|
||||
return PIN_NIL;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Chip::Chip(ChipArgs args)
|
||||
{
|
||||
if (args.type == ChipArgs::LP384) {
|
||||
chip_info = chip_info_384;
|
||||
return;
|
||||
} else if (args.type == ChipArgs::LP1K || args.type == ChipArgs::HX1K) {
|
||||
chip_info = chip_info_1k;
|
||||
return;
|
||||
} else if (args.type == ChipArgs::UP5K) {
|
||||
chip_info = chip_info_5k;
|
||||
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);
|
||||
}
|
||||
#ifdef ICE40_HX1K_ONLY
|
||||
if (args.type == ChipArgs::HX1K) {
|
||||
chip_info = chip_info_1k;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (args.type == ChipArgs::LP384) {
|
||||
chip_info = chip_info_384;
|
||||
return;
|
||||
} else if (args.type == ChipArgs::LP1K || args.type == ChipArgs::HX1K) {
|
||||
chip_info = chip_info_1k;
|
||||
return;
|
||||
} else if (args.type == ChipArgs::UP5K) {
|
||||
chip_info = chip_info_5k;
|
||||
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 ret;
|
||||
BelId ret;
|
||||
|
||||
if (bel_by_name.empty()) {
|
||||
for (int i = 0; i < chip_info.num_bels; i++)
|
||||
bel_by_name[chip_info.bel_data[i].name] = i;
|
||||
}
|
||||
if (bel_by_name.empty()) {
|
||||
for (int i = 0; i < chip_info.num_bels; i++)
|
||||
bel_by_name[chip_info.bel_data[i].name] = i;
|
||||
}
|
||||
|
||||
auto it = bel_by_name.find(name);
|
||||
if (it != bel_by_name.end())
|
||||
ret.index = it->second;
|
||||
auto it = bel_by_name.find(name);
|
||||
if (it != bel_by_name.end())
|
||||
ret.index = it->second;
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
WireId Chip::getWireBelPin(BelId bel, PortPin pin) const
|
||||
{
|
||||
// FIXME
|
||||
return WireId();
|
||||
// FIXME
|
||||
return WireId();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
WireId Chip::getWireByName(IdString name) const
|
||||
{
|
||||
WireId ret;
|
||||
WireId ret;
|
||||
|
||||
if (wire_by_name.empty()) {
|
||||
for (int i = 0; i < chip_info.num_wires; i++)
|
||||
wire_by_name[chip_info.wire_data[i].name] = i;
|
||||
}
|
||||
if (wire_by_name.empty()) {
|
||||
for (int i = 0; i < chip_info.num_wires; i++)
|
||||
wire_by_name[chip_info.wire_data[i].name] = i;
|
||||
}
|
||||
|
||||
auto it = wire_by_name.find(name);
|
||||
if (it != wire_by_name.end())
|
||||
ret.index = it->second;
|
||||
auto it = wire_by_name.find(name);
|
||||
if (it != wire_by_name.end())
|
||||
ret.index = it->second;
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
PipId Chip::getPipByName(IdString name) const
|
||||
{
|
||||
PipId ret;
|
||||
PipId ret;
|
||||
|
||||
if (pip_by_name.empty()) {
|
||||
for (int i = 0; i < chip_info.num_pips; i++) {
|
||||
PipId pip;
|
||||
pip.index = i;
|
||||
pip_by_name[getPipName(pip)] = i;
|
||||
}
|
||||
}
|
||||
if (pip_by_name.empty()) {
|
||||
for (int i = 0; i < chip_info.num_pips; i++) {
|
||||
PipId pip;
|
||||
pip.index = i;
|
||||
pip_by_name[getPipName(pip)] = i;
|
||||
}
|
||||
}
|
||||
|
||||
auto it = pip_by_name.find(name);
|
||||
if (it != pip_by_name.end())
|
||||
ret.index = it->second;
|
||||
auto it = pip_by_name.find(name);
|
||||
if (it != pip_by_name.end())
|
||||
ret.index = it->second;
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void Chip::getBelPosition(BelId bel, float &x, float &y) const
|
||||
{
|
||||
assert(!bel.nil());
|
||||
x = chip_info.bel_data[bel.index].x;
|
||||
y = chip_info.bel_data[bel.index].y;
|
||||
assert(!bel.nil());
|
||||
x = chip_info.bel_data[bel.index].x;
|
||||
y = chip_info.bel_data[bel.index].y;
|
||||
}
|
||||
|
||||
void Chip::getWirePosition(WireId wire, float &x, float &y) const
|
||||
{
|
||||
assert(!wire.nil());
|
||||
x = chip_info.wire_data[wire.index].x;
|
||||
y = chip_info.wire_data[wire.index].y;
|
||||
assert(!wire.nil());
|
||||
x = chip_info.wire_data[wire.index].x;
|
||||
y = chip_info.wire_data[wire.index].y;
|
||||
}
|
||||
|
||||
void Chip::getPipPosition(PipId pip, float &x, float &y) const
|
||||
{
|
||||
assert(!pip.nil());
|
||||
x = chip_info.pip_data[pip.index].x;
|
||||
y = chip_info.pip_data[pip.index].y;
|
||||
assert(!pip.nil());
|
||||
x = chip_info.pip_data[pip.index].x;
|
||||
y = chip_info.pip_data[pip.index].y;
|
||||
}
|
||||
|
||||
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) {
|
||||
GraphicElement el;
|
||||
el.type = GraphicElement::G_BOX;
|
||||
el.x1 = chip_info.bel_data[bel.index].x + 0.1;
|
||||
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.y2 = chip_info.bel_data[bel.index].y + 0.18 + (chip_info.bel_data[bel.index].z) * (0.8/8);
|
||||
el.z = 0;
|
||||
ret.push_back(el);
|
||||
}
|
||||
if (bel_type == TYPE_ICESTORM_LC) {
|
||||
GraphicElement el;
|
||||
el.type = GraphicElement::G_BOX;
|
||||
el.x1 = chip_info.bel_data[bel.index].x + 0.1;
|
||||
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.y2 = chip_info.bel_data[bel.index].y + 0.18 +
|
||||
(chip_info.bel_data[bel.index].z) * (0.8 / 8);
|
||||
el.z = 0;
|
||||
ret.push_back(el);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
GraphicElement el;
|
||||
el.type = GraphicElement::G_BOX;
|
||||
el.x1 = chip_info.bel_data[bel.index].x + 0.1;
|
||||
el.x2 = chip_info.bel_data[bel.index].x + 0.9;
|
||||
if (chip_info.bel_data[bel.index].z == 0) {
|
||||
el.y1 = chip_info.bel_data[bel.index].y + 0.10;
|
||||
el.y2 = chip_info.bel_data[bel.index].y + 0.45;
|
||||
} else {
|
||||
el.y1 = chip_info.bel_data[bel.index].y + 0.55;
|
||||
el.y2 = chip_info.bel_data[bel.index].y + 0.90;
|
||||
}
|
||||
el.z = 0;
|
||||
ret.push_back(el);
|
||||
}
|
||||
else
|
||||
{
|
||||
GraphicElement el;
|
||||
el.type = GraphicElement::G_BOX;
|
||||
if (chip_info.bel_data[bel.index].z == 0) {
|
||||
el.x1 = chip_info.bel_data[bel.index].x + 0.10;
|
||||
el.x2 = chip_info.bel_data[bel.index].x + 0.45;
|
||||
} else {
|
||||
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.z = 0;
|
||||
ret.push_back(el);
|
||||
}
|
||||
}
|
||||
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) {
|
||||
GraphicElement el;
|
||||
el.type = GraphicElement::G_BOX;
|
||||
el.x1 = chip_info.bel_data[bel.index].x + 0.1;
|
||||
el.x2 = chip_info.bel_data[bel.index].x + 0.9;
|
||||
if (chip_info.bel_data[bel.index].z == 0) {
|
||||
el.y1 = chip_info.bel_data[bel.index].y + 0.10;
|
||||
el.y2 = chip_info.bel_data[bel.index].y + 0.45;
|
||||
} else {
|
||||
el.y1 = chip_info.bel_data[bel.index].y + 0.55;
|
||||
el.y2 = chip_info.bel_data[bel.index].y + 0.90;
|
||||
}
|
||||
el.z = 0;
|
||||
ret.push_back(el);
|
||||
} else {
|
||||
GraphicElement el;
|
||||
el.type = GraphicElement::G_BOX;
|
||||
if (chip_info.bel_data[bel.index].z == 0) {
|
||||
el.x1 = chip_info.bel_data[bel.index].x + 0.10;
|
||||
el.x2 = chip_info.bel_data[bel.index].x + 0.45;
|
||||
} else {
|
||||
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.z = 0;
|
||||
ret.push_back(el);
|
||||
}
|
||||
}
|
||||
|
||||
if (bel_type == TYPE_ICESTORM_RAM) {
|
||||
GraphicElement el;
|
||||
el.type = GraphicElement::G_BOX;
|
||||
el.x1 = chip_info.bel_data[bel.index].x + 0.1;
|
||||
el.x2 = chip_info.bel_data[bel.index].x + 0.9;
|
||||
el.y1 = chip_info.bel_data[bel.index].y + 0.1;
|
||||
el.y2 = chip_info.bel_data[bel.index].y + 1.9;
|
||||
el.z = 0;
|
||||
ret.push_back(el);
|
||||
}
|
||||
if (bel_type == TYPE_ICESTORM_RAM) {
|
||||
GraphicElement el;
|
||||
el.type = GraphicElement::G_BOX;
|
||||
el.x1 = chip_info.bel_data[bel.index].x + 0.1;
|
||||
el.x2 = chip_info.bel_data[bel.index].x + 0.9;
|
||||
el.y1 = chip_info.bel_data[bel.index].y + 0.1;
|
||||
el.y2 = chip_info.bel_data[bel.index].y + 1.9;
|
||||
el.z = 0;
|
||||
ret.push_back(el);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
vector<GraphicElement> Chip::getWireGraphics(WireId wire) const
|
||||
{
|
||||
vector<GraphicElement> ret;
|
||||
// FIXME
|
||||
return ret;
|
||||
vector<GraphicElement> ret;
|
||||
// FIXME
|
||||
return ret;
|
||||
}
|
||||
|
||||
vector<GraphicElement> Chip::getPipGraphics(PipId pip) const
|
||||
{
|
||||
vector<GraphicElement> ret;
|
||||
// FIXME
|
||||
return ret;
|
||||
vector<GraphicElement> ret;
|
||||
// FIXME
|
||||
return ret;
|
||||
}
|
||||
|
||||
vector<GraphicElement> Chip::getFrameGraphics() const
|
||||
{
|
||||
vector<GraphicElement> ret;
|
||||
vector<GraphicElement> ret;
|
||||
|
||||
for (int x = 0; x <= chip_info.width; x++)
|
||||
for (int y = 0; y <= chip_info.height; y++)
|
||||
{
|
||||
GraphicElement el;
|
||||
el.type = GraphicElement::G_LINE;
|
||||
el.x1 = x - 0.05, el.x2 = x + 0.05, el.y1 = y, el.y2 = y, el.z = 0;
|
||||
ret.push_back(el);
|
||||
el.x1 = x, el.x2 = x, el.y1 = y - 0.05, el.y2 = y + 0.05, el.z = 0;
|
||||
ret.push_back(el);
|
||||
}
|
||||
for (int x = 0; x <= chip_info.width; x++)
|
||||
for (int y = 0; y <= chip_info.height; y++) {
|
||||
GraphicElement el;
|
||||
el.type = GraphicElement::G_LINE;
|
||||
el.x1 = x - 0.05, el.x2 = x + 0.05, el.y1 = y, el.y2 = y, el.z = 0;
|
||||
ret.push_back(el);
|
||||
el.x1 = x, el.x2 = x, el.y1 = y - 0.05, el.y2 = y + 0.05, el.z = 0;
|
||||
ret.push_back(el);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
785
ice40/chip.h
785
ice40/chip.h
@ -24,20 +24,20 @@
|
||||
|
||||
struct DelayInfo
|
||||
{
|
||||
float delay = 0;
|
||||
float delay = 0;
|
||||
|
||||
float raiseDelay() { return delay; }
|
||||
float fallDelay() { return delay; }
|
||||
float raiseDelay() { return delay; }
|
||||
float fallDelay() { return delay; }
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
enum BelType
|
||||
{
|
||||
TYPE_NIL,
|
||||
TYPE_ICESTORM_LC,
|
||||
TYPE_ICESTORM_RAM,
|
||||
TYPE_SB_IO
|
||||
TYPE_NIL,
|
||||
TYPE_ICESTORM_LC,
|
||||
TYPE_ICESTORM_RAM,
|
||||
TYPE_SB_IO
|
||||
};
|
||||
|
||||
IdString belTypeToId(BelType type);
|
||||
@ -45,113 +45,113 @@ BelType belTypeFromId(IdString id);
|
||||
|
||||
enum PortPin
|
||||
{
|
||||
PIN_NIL,
|
||||
PIN_NIL,
|
||||
|
||||
PIN_IN_0,
|
||||
PIN_IN_1,
|
||||
PIN_IN_2,
|
||||
PIN_IN_3,
|
||||
PIN_O,
|
||||
PIN_LO,
|
||||
PIN_CIN,
|
||||
PIN_COUT,
|
||||
PIN_CEN,
|
||||
PIN_CLK,
|
||||
PIN_SR,
|
||||
PIN_IN_0,
|
||||
PIN_IN_1,
|
||||
PIN_IN_2,
|
||||
PIN_IN_3,
|
||||
PIN_O,
|
||||
PIN_LO,
|
||||
PIN_CIN,
|
||||
PIN_COUT,
|
||||
PIN_CEN,
|
||||
PIN_CLK,
|
||||
PIN_SR,
|
||||
|
||||
PIN_MASK_0,
|
||||
PIN_MASK_1,
|
||||
PIN_MASK_2,
|
||||
PIN_MASK_3,
|
||||
PIN_MASK_4,
|
||||
PIN_MASK_5,
|
||||
PIN_MASK_6,
|
||||
PIN_MASK_7,
|
||||
PIN_MASK_8,
|
||||
PIN_MASK_9,
|
||||
PIN_MASK_10,
|
||||
PIN_MASK_11,
|
||||
PIN_MASK_12,
|
||||
PIN_MASK_13,
|
||||
PIN_MASK_14,
|
||||
PIN_MASK_15,
|
||||
PIN_MASK_0,
|
||||
PIN_MASK_1,
|
||||
PIN_MASK_2,
|
||||
PIN_MASK_3,
|
||||
PIN_MASK_4,
|
||||
PIN_MASK_5,
|
||||
PIN_MASK_6,
|
||||
PIN_MASK_7,
|
||||
PIN_MASK_8,
|
||||
PIN_MASK_9,
|
||||
PIN_MASK_10,
|
||||
PIN_MASK_11,
|
||||
PIN_MASK_12,
|
||||
PIN_MASK_13,
|
||||
PIN_MASK_14,
|
||||
PIN_MASK_15,
|
||||
|
||||
PIN_RDATA_0,
|
||||
PIN_RDATA_1,
|
||||
PIN_RDATA_2,
|
||||
PIN_RDATA_3,
|
||||
PIN_RDATA_4,
|
||||
PIN_RDATA_5,
|
||||
PIN_RDATA_6,
|
||||
PIN_RDATA_7,
|
||||
PIN_RDATA_8,
|
||||
PIN_RDATA_9,
|
||||
PIN_RDATA_10,
|
||||
PIN_RDATA_11,
|
||||
PIN_RDATA_12,
|
||||
PIN_RDATA_13,
|
||||
PIN_RDATA_14,
|
||||
PIN_RDATA_15,
|
||||
PIN_RDATA_0,
|
||||
PIN_RDATA_1,
|
||||
PIN_RDATA_2,
|
||||
PIN_RDATA_3,
|
||||
PIN_RDATA_4,
|
||||
PIN_RDATA_5,
|
||||
PIN_RDATA_6,
|
||||
PIN_RDATA_7,
|
||||
PIN_RDATA_8,
|
||||
PIN_RDATA_9,
|
||||
PIN_RDATA_10,
|
||||
PIN_RDATA_11,
|
||||
PIN_RDATA_12,
|
||||
PIN_RDATA_13,
|
||||
PIN_RDATA_14,
|
||||
PIN_RDATA_15,
|
||||
|
||||
PIN_WDATA_0,
|
||||
PIN_WDATA_1,
|
||||
PIN_WDATA_2,
|
||||
PIN_WDATA_3,
|
||||
PIN_WDATA_4,
|
||||
PIN_WDATA_5,
|
||||
PIN_WDATA_6,
|
||||
PIN_WDATA_7,
|
||||
PIN_WDATA_8,
|
||||
PIN_WDATA_9,
|
||||
PIN_WDATA_10,
|
||||
PIN_WDATA_11,
|
||||
PIN_WDATA_12,
|
||||
PIN_WDATA_13,
|
||||
PIN_WDATA_14,
|
||||
PIN_WDATA_15,
|
||||
PIN_WDATA_0,
|
||||
PIN_WDATA_1,
|
||||
PIN_WDATA_2,
|
||||
PIN_WDATA_3,
|
||||
PIN_WDATA_4,
|
||||
PIN_WDATA_5,
|
||||
PIN_WDATA_6,
|
||||
PIN_WDATA_7,
|
||||
PIN_WDATA_8,
|
||||
PIN_WDATA_9,
|
||||
PIN_WDATA_10,
|
||||
PIN_WDATA_11,
|
||||
PIN_WDATA_12,
|
||||
PIN_WDATA_13,
|
||||
PIN_WDATA_14,
|
||||
PIN_WDATA_15,
|
||||
|
||||
PIN_WADDR_0,
|
||||
PIN_WADDR_1,
|
||||
PIN_WADDR_2,
|
||||
PIN_WADDR_3,
|
||||
PIN_WADDR_4,
|
||||
PIN_WADDR_5,
|
||||
PIN_WADDR_6,
|
||||
PIN_WADDR_7,
|
||||
PIN_WADDR_8,
|
||||
PIN_WADDR_9,
|
||||
PIN_WADDR_10,
|
||||
PIN_WADDR_0,
|
||||
PIN_WADDR_1,
|
||||
PIN_WADDR_2,
|
||||
PIN_WADDR_3,
|
||||
PIN_WADDR_4,
|
||||
PIN_WADDR_5,
|
||||
PIN_WADDR_6,
|
||||
PIN_WADDR_7,
|
||||
PIN_WADDR_8,
|
||||
PIN_WADDR_9,
|
||||
PIN_WADDR_10,
|
||||
|
||||
PIN_RADDR_0,
|
||||
PIN_RADDR_1,
|
||||
PIN_RADDR_2,
|
||||
PIN_RADDR_3,
|
||||
PIN_RADDR_4,
|
||||
PIN_RADDR_5,
|
||||
PIN_RADDR_6,
|
||||
PIN_RADDR_7,
|
||||
PIN_RADDR_8,
|
||||
PIN_RADDR_9,
|
||||
PIN_RADDR_10,
|
||||
PIN_RADDR_0,
|
||||
PIN_RADDR_1,
|
||||
PIN_RADDR_2,
|
||||
PIN_RADDR_3,
|
||||
PIN_RADDR_4,
|
||||
PIN_RADDR_5,
|
||||
PIN_RADDR_6,
|
||||
PIN_RADDR_7,
|
||||
PIN_RADDR_8,
|
||||
PIN_RADDR_9,
|
||||
PIN_RADDR_10,
|
||||
|
||||
PIN_WCLK,
|
||||
PIN_WCLKE,
|
||||
PIN_WE,
|
||||
PIN_WCLK,
|
||||
PIN_WCLKE,
|
||||
PIN_WE,
|
||||
|
||||
PIN_RCLK,
|
||||
PIN_RCLKE,
|
||||
PIN_RE,
|
||||
PIN_RCLK,
|
||||
PIN_RCLKE,
|
||||
PIN_RE,
|
||||
|
||||
PIN_PACKAGE_PIN,
|
||||
PIN_LATCH_INPUT_VALUE,
|
||||
PIN_CLOCK_ENABLE,
|
||||
PIN_INPUT_CLK,
|
||||
PIN_OUTPUT_CLK,
|
||||
PIN_OUTPUT_ENABLE,
|
||||
PIN_D_OUT_0,
|
||||
PIN_D_OUT_1,
|
||||
PIN_D_IN_0,
|
||||
PIN_D_IN_1
|
||||
PIN_PACKAGE_PIN,
|
||||
PIN_LATCH_INPUT_VALUE,
|
||||
PIN_CLOCK_ENABLE,
|
||||
PIN_INPUT_CLK,
|
||||
PIN_OUTPUT_CLK,
|
||||
PIN_OUTPUT_ENABLE,
|
||||
PIN_D_OUT_0,
|
||||
PIN_D_OUT_1,
|
||||
PIN_D_IN_0,
|
||||
PIN_D_IN_1
|
||||
};
|
||||
|
||||
IdString PortPinToId(PortPin type);
|
||||
@ -159,47 +159,46 @@ PortPin PortPinFromId(IdString id);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
struct BelInfoPOD
|
||||
{
|
||||
const char *name;
|
||||
BelType type;
|
||||
int8_t x, y, z;
|
||||
const char *name;
|
||||
BelType type;
|
||||
int8_t x, y, z;
|
||||
};
|
||||
|
||||
struct BelPortPOD
|
||||
{
|
||||
int32_t bel_index;
|
||||
PortPin port;
|
||||
int32_t bel_index;
|
||||
PortPin port;
|
||||
};
|
||||
|
||||
struct PipInfoPOD
|
||||
{
|
||||
int32_t src, dst;
|
||||
float delay;
|
||||
int8_t x, y;
|
||||
int32_t src, dst;
|
||||
float delay;
|
||||
int8_t x, y;
|
||||
};
|
||||
|
||||
struct WireInfoPOD
|
||||
{
|
||||
const char *name;
|
||||
int num_uphill, num_downhill;
|
||||
int *pips_uphill, *pips_downhill;
|
||||
const char *name;
|
||||
int num_uphill, num_downhill;
|
||||
int *pips_uphill, *pips_downhill;
|
||||
|
||||
int num_bels_downhill;
|
||||
BelPortPOD bel_uphill;
|
||||
BelPortPOD *bels_downhill;
|
||||
int num_bels_downhill;
|
||||
BelPortPOD bel_uphill;
|
||||
BelPortPOD *bels_downhill;
|
||||
|
||||
float x, y;
|
||||
float x, y;
|
||||
};
|
||||
|
||||
struct ChipInfoPOD
|
||||
{
|
||||
int width, height;
|
||||
int num_bels, num_wires, num_pips;
|
||||
BelInfoPOD *bel_data;
|
||||
WireInfoPOD *wire_data;
|
||||
PipInfoPOD *pip_data;
|
||||
int width, height;
|
||||
int num_bels, num_wires, num_pips;
|
||||
BelInfoPOD *bel_data;
|
||||
WireInfoPOD *wire_data;
|
||||
PipInfoPOD *pip_data;
|
||||
};
|
||||
|
||||
extern ChipInfoPOD chip_info_384;
|
||||
@ -211,248 +210,256 @@ extern ChipInfoPOD chip_info_8k;
|
||||
|
||||
struct BelId
|
||||
{
|
||||
int32_t index = -1;
|
||||
int32_t index = -1;
|
||||
|
||||
bool nil() const {
|
||||
return index < 0;
|
||||
}
|
||||
bool nil() const { 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
|
||||
{
|
||||
int32_t index = -1;
|
||||
int32_t index = -1;
|
||||
|
||||
bool nil() const {
|
||||
return index < 0;
|
||||
}
|
||||
bool nil() const { 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
|
||||
{
|
||||
int32_t index = -1;
|
||||
int32_t index = -1;
|
||||
|
||||
bool nil() const {
|
||||
return index < 0;
|
||||
}
|
||||
bool nil() const { 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
|
||||
{
|
||||
BelId bel;
|
||||
PortPin pin;
|
||||
BelId bel;
|
||||
PortPin pin;
|
||||
};
|
||||
|
||||
namespace std
|
||||
namespace std {
|
||||
template <> struct hash<BelId>
|
||||
{
|
||||
template<> struct hash<BelId>
|
||||
{
|
||||
std::size_t operator()(const BelId &bel) const noexcept
|
||||
{
|
||||
return bel.index;
|
||||
}
|
||||
};
|
||||
std::size_t operator()(const BelId &bel) const noexcept
|
||||
{
|
||||
return bel.index;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct hash<WireId>
|
||||
{
|
||||
std::size_t operator()(const WireId &wire) const noexcept
|
||||
{
|
||||
return wire.index;
|
||||
}
|
||||
};
|
||||
template <> struct hash<WireId>
|
||||
{
|
||||
std::size_t operator()(const WireId &wire) const noexcept
|
||||
{
|
||||
return wire.index;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct hash<PipId>
|
||||
{
|
||||
std::size_t operator()(const PipId &wire) const noexcept
|
||||
{
|
||||
return wire.index;
|
||||
}
|
||||
};
|
||||
template <> struct hash<PipId>
|
||||
{
|
||||
std::size_t operator()(const PipId &wire) const noexcept
|
||||
{
|
||||
return wire.index;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
struct BelIterator
|
||||
{
|
||||
int cursor;
|
||||
int cursor;
|
||||
|
||||
void operator++() { cursor++; }
|
||||
bool operator!=(const BelIterator &other) const { return cursor != other.cursor; }
|
||||
void operator++() { cursor++; }
|
||||
bool operator!=(const BelIterator &other) const
|
||||
{
|
||||
return cursor != other.cursor;
|
||||
}
|
||||
|
||||
BelId operator*() const {
|
||||
BelId ret;
|
||||
ret.index = cursor;
|
||||
return ret;
|
||||
}
|
||||
BelId operator*() const
|
||||
{
|
||||
BelId ret;
|
||||
ret.index = cursor;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct BelRange
|
||||
{
|
||||
BelIterator b, e;
|
||||
BelIterator begin() const { return b; }
|
||||
BelIterator end() const { return e; }
|
||||
BelIterator b, e;
|
||||
BelIterator begin() const { return b; }
|
||||
BelIterator end() const { return e; }
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
struct BelPinIterator
|
||||
{
|
||||
BelPortPOD *ptr = nullptr;
|
||||
BelPortPOD *ptr = nullptr;
|
||||
|
||||
void operator++() { ptr++; }
|
||||
bool operator!=(const BelPinIterator &other) const { return ptr != other.ptr; }
|
||||
void operator++() { ptr++; }
|
||||
bool operator!=(const BelPinIterator &other) const
|
||||
{
|
||||
return ptr != other.ptr;
|
||||
}
|
||||
|
||||
BelPin operator*() const {
|
||||
BelPin ret;
|
||||
ret.bel.index = ptr->bel_index;
|
||||
ret.pin = ptr->port;
|
||||
return ret;
|
||||
}
|
||||
BelPin operator*() const
|
||||
{
|
||||
BelPin ret;
|
||||
ret.bel.index = ptr->bel_index;
|
||||
ret.pin = ptr->port;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct BelPinRange
|
||||
{
|
||||
BelPinIterator b, e;
|
||||
BelPinIterator begin() const { return b; }
|
||||
BelPinIterator end() const { return e; }
|
||||
BelPinIterator b, e;
|
||||
BelPinIterator begin() const { return b; }
|
||||
BelPinIterator end() const { return e; }
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
struct WireIterator
|
||||
{
|
||||
int cursor = -1;
|
||||
int cursor = -1;
|
||||
|
||||
void operator++() { cursor++; }
|
||||
bool operator!=(const WireIterator &other) const { return cursor != other.cursor; }
|
||||
void operator++() { cursor++; }
|
||||
bool operator!=(const WireIterator &other) const
|
||||
{
|
||||
return cursor != other.cursor;
|
||||
}
|
||||
|
||||
WireId operator*() const {
|
||||
WireId ret;
|
||||
ret.index = cursor;
|
||||
return ret;
|
||||
}
|
||||
WireId operator*() const
|
||||
{
|
||||
WireId ret;
|
||||
ret.index = cursor;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct WireRange
|
||||
{
|
||||
WireIterator b, e;
|
||||
WireIterator begin() const { return b; }
|
||||
WireIterator end() const { return e; }
|
||||
WireIterator b, e;
|
||||
WireIterator begin() const { return b; }
|
||||
WireIterator end() const { return e; }
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
struct AllPipIterator
|
||||
{
|
||||
int cursor = -1;
|
||||
int cursor = -1;
|
||||
|
||||
void operator++() { cursor++; }
|
||||
bool operator!=(const AllPipIterator &other) const { return cursor != other.cursor; }
|
||||
void operator++() { cursor++; }
|
||||
bool operator!=(const AllPipIterator &other) const
|
||||
{
|
||||
return cursor != other.cursor;
|
||||
}
|
||||
|
||||
PipId operator*() const {
|
||||
PipId ret;
|
||||
ret.index = cursor;
|
||||
return ret;
|
||||
}
|
||||
PipId operator*() const
|
||||
{
|
||||
PipId ret;
|
||||
ret.index = cursor;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct AllPipRange
|
||||
{
|
||||
AllPipIterator b, e;
|
||||
AllPipIterator begin() const { return b; }
|
||||
AllPipIterator end() const { return e; }
|
||||
AllPipIterator b, e;
|
||||
AllPipIterator begin() const { return b; }
|
||||
AllPipIterator end() const { return e; }
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
struct PipIterator
|
||||
{
|
||||
int *cursor = nullptr;
|
||||
int *cursor = nullptr;
|
||||
|
||||
void operator++() { cursor++; }
|
||||
bool operator!=(const PipIterator &other) const { return cursor != other.cursor; }
|
||||
void operator++() { cursor++; }
|
||||
bool operator!=(const PipIterator &other) const
|
||||
{
|
||||
return cursor != other.cursor;
|
||||
}
|
||||
|
||||
PipId operator*() const {
|
||||
PipId ret;
|
||||
ret.index = *cursor;
|
||||
return ret;
|
||||
}
|
||||
PipId operator*() const
|
||||
{
|
||||
PipId ret;
|
||||
ret.index = *cursor;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct PipRange
|
||||
{
|
||||
PipIterator b, e;
|
||||
PipIterator begin() const { return b; }
|
||||
PipIterator end() const { return e; }
|
||||
PipIterator b, e;
|
||||
PipIterator begin() const { return b; }
|
||||
PipIterator end() const { return e; }
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
struct ChipArgs
|
||||
{
|
||||
enum {
|
||||
NONE,
|
||||
LP384,
|
||||
LP1K,
|
||||
LP8K,
|
||||
HX1K,
|
||||
HX8K,
|
||||
UP5K
|
||||
} type = NONE;
|
||||
enum
|
||||
{
|
||||
NONE,
|
||||
LP384,
|
||||
LP1K,
|
||||
LP8K,
|
||||
HX1K,
|
||||
HX8K,
|
||||
UP5K
|
||||
} type = NONE;
|
||||
};
|
||||
|
||||
struct Chip
|
||||
{
|
||||
ChipInfoPOD chip_info;
|
||||
ChipInfoPOD chip_info;
|
||||
|
||||
mutable dict<IdString, int> bel_by_name;
|
||||
mutable dict<IdString, int> wire_by_name;
|
||||
mutable dict<IdString, int> pip_by_name;
|
||||
mutable dict<IdString, int> bel_by_name;
|
||||
mutable dict<IdString, int> wire_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
|
||||
{
|
||||
assert(!bel.nil());
|
||||
return chip_info.bel_data[bel.index].name;
|
||||
}
|
||||
IdString getBelName(BelId bel) const
|
||||
{
|
||||
assert(!bel.nil());
|
||||
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 range;
|
||||
range.b.cursor = 0;
|
||||
range.e.cursor = chip_info.num_bels;
|
||||
return range;
|
||||
}
|
||||
BelRange getBels() const
|
||||
{
|
||||
BelRange range;
|
||||
range.b.cursor = 0;
|
||||
range.e.cursor = chip_info.num_bels;
|
||||
return range;
|
||||
}
|
||||
|
||||
BelRange getBelsByType(BelType type) const
|
||||
{
|
||||
BelRange range;
|
||||
// FIXME
|
||||
BelRange getBelsByType(BelType type) const
|
||||
{
|
||||
BelRange range;
|
||||
// FIXME
|
||||
#if 0
|
||||
if (type == "TYPE_A") {
|
||||
range.b.cursor = bels_type_a_begin;
|
||||
@ -460,161 +467,155 @@ struct Chip
|
||||
}
|
||||
...
|
||||
#endif
|
||||
return range;
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
BelType getBelType(BelId bel) const
|
||||
{
|
||||
assert(!bel.nil());
|
||||
return chip_info.bel_data[bel.index].type;
|
||||
}
|
||||
BelType getBelType(BelId bel) const
|
||||
{
|
||||
assert(!bel.nil());
|
||||
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 ret;
|
||||
assert(!wire.nil());
|
||||
BelPin getBelPinUphill(WireId wire) const
|
||||
{
|
||||
BelPin ret;
|
||||
assert(!wire.nil());
|
||||
|
||||
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.pin = chip_info.wire_data[wire.index].bel_uphill.port;
|
||||
}
|
||||
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.pin = chip_info.wire_data[wire.index].bel_uphill.port;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
BelPinRange getBelPinsDownhill(WireId wire) const
|
||||
{
|
||||
BelPinRange range;
|
||||
assert(!wire.nil());
|
||||
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;
|
||||
return range;
|
||||
}
|
||||
BelPinRange getBelPinsDownhill(WireId wire) const
|
||||
{
|
||||
BelPinRange range;
|
||||
assert(!wire.nil());
|
||||
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;
|
||||
return range;
|
||||
}
|
||||
|
||||
// -------------------------------------------------
|
||||
// -------------------------------------------------
|
||||
|
||||
WireId getWireByName(IdString name) const;
|
||||
WireId getWireByName(IdString name) const;
|
||||
|
||||
IdString getWireName(WireId wire) const
|
||||
{
|
||||
assert(!wire.nil());
|
||||
return chip_info.wire_data[wire.index].name;
|
||||
}
|
||||
IdString getWireName(WireId wire) const
|
||||
{
|
||||
assert(!wire.nil());
|
||||
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 range;
|
||||
range.b.cursor = 0;
|
||||
range.e.cursor = chip_info.num_wires;
|
||||
return range;
|
||||
}
|
||||
WireRange getWires() const
|
||||
{
|
||||
WireRange range;
|
||||
range.b.cursor = 0;
|
||||
range.e.cursor = chip_info.num_wires;
|
||||
return range;
|
||||
}
|
||||
|
||||
// -------------------------------------------------
|
||||
// -------------------------------------------------
|
||||
|
||||
PipId getPipByName(IdString name) const;
|
||||
PipId getPipByName(IdString name) const;
|
||||
|
||||
IdString getPipName(PipId pip) const
|
||||
{
|
||||
assert(!pip.nil());
|
||||
std::string src_name = chip_info.wire_data[chip_info.pip_data[pip.index].src].name;
|
||||
std::string dst_name = chip_info.wire_data[chip_info.pip_data[pip.index].dst].name;
|
||||
return src_name + "->" + dst_name;
|
||||
}
|
||||
IdString getPipName(PipId pip) const
|
||||
{
|
||||
assert(!pip.nil());
|
||||
std::string src_name =
|
||||
chip_info.wire_data[chip_info.pip_data[pip.index].src].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 range;
|
||||
range.b.cursor = 0;
|
||||
range.e.cursor = chip_info.num_pips;
|
||||
return range;
|
||||
}
|
||||
AllPipRange getPips() const
|
||||
{
|
||||
AllPipRange range;
|
||||
range.b.cursor = 0;
|
||||
range.e.cursor = chip_info.num_pips;
|
||||
return range;
|
||||
}
|
||||
|
||||
WireId getPipSrcWire(PipId pip) const
|
||||
{
|
||||
WireId wire;
|
||||
assert(!pip.nil());
|
||||
wire.index = chip_info.pip_data[pip.index].src;
|
||||
return wire;
|
||||
}
|
||||
WireId getPipSrcWire(PipId pip) const
|
||||
{
|
||||
WireId wire;
|
||||
assert(!pip.nil());
|
||||
wire.index = chip_info.pip_data[pip.index].src;
|
||||
return wire;
|
||||
}
|
||||
|
||||
WireId getPipDstWire(PipId pip) const
|
||||
{
|
||||
WireId wire;
|
||||
assert(!pip.nil());
|
||||
wire.index = chip_info.pip_data[pip.index].dst;
|
||||
return wire;
|
||||
}
|
||||
WireId getPipDstWire(PipId pip) const
|
||||
{
|
||||
WireId wire;
|
||||
assert(!pip.nil());
|
||||
wire.index = chip_info.pip_data[pip.index].dst;
|
||||
return wire;
|
||||
}
|
||||
|
||||
DelayInfo getPipDelay(PipId pip) const
|
||||
{
|
||||
DelayInfo delay;
|
||||
assert(!pip.nil());
|
||||
delay.delay = chip_info.pip_data[pip.index].delay;
|
||||
return delay;
|
||||
}
|
||||
DelayInfo getPipDelay(PipId pip) const
|
||||
{
|
||||
DelayInfo delay;
|
||||
assert(!pip.nil());
|
||||
delay.delay = chip_info.pip_data[pip.index].delay;
|
||||
return delay;
|
||||
}
|
||||
|
||||
PipRange getPipsDownhill(WireId wire) const
|
||||
{
|
||||
PipRange range;
|
||||
assert(!wire.nil());
|
||||
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;
|
||||
return range;
|
||||
}
|
||||
PipRange getPipsDownhill(WireId wire) const
|
||||
{
|
||||
PipRange range;
|
||||
assert(!wire.nil());
|
||||
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;
|
||||
return range;
|
||||
}
|
||||
|
||||
PipRange getPipsUphill(WireId wire) const
|
||||
{
|
||||
PipRange range;
|
||||
assert(!wire.nil());
|
||||
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;
|
||||
return range;
|
||||
}
|
||||
PipRange getPipsUphill(WireId wire) const
|
||||
{
|
||||
PipRange range;
|
||||
assert(!wire.nil());
|
||||
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;
|
||||
return range;
|
||||
}
|
||||
|
||||
PipRange getWireAliases(WireId wire) const
|
||||
{
|
||||
PipRange range;
|
||||
assert(!wire.nil());
|
||||
range.b.cursor = nullptr;
|
||||
range.e.cursor = nullptr;
|
||||
return range;
|
||||
}
|
||||
PipRange getWireAliases(WireId wire) const
|
||||
{
|
||||
PipRange range;
|
||||
assert(!wire.nil());
|
||||
range.b.cursor = nullptr;
|
||||
range.e.cursor = nullptr;
|
||||
return range;
|
||||
}
|
||||
|
||||
// -------------------------------------------------
|
||||
// -------------------------------------------------
|
||||
|
||||
void getBelPosition(BelId bel, float &x, float &y) const;
|
||||
void getWirePosition(WireId wire, float &x, float &y) const;
|
||||
void getPipPosition(PipId pip, float &x, float &y) const;
|
||||
vector<GraphicElement> getBelGraphics(BelId bel) const;
|
||||
vector<GraphicElement> getWireGraphics(WireId wire) const;
|
||||
vector<GraphicElement> getPipGraphics(PipId pip) const;
|
||||
vector<GraphicElement> getFrameGraphics() const;
|
||||
void getBelPosition(BelId bel, float &x, float &y) const;
|
||||
void getWirePosition(WireId wire, float &x, float &y) const;
|
||||
void getPipPosition(PipId pip, float &x, float &y) const;
|
||||
vector<GraphicElement> getBelGraphics(BelId bel) const;
|
||||
vector<GraphicElement> getWireGraphics(WireId wire) const;
|
||||
vector<GraphicElement> getPipGraphics(PipId pip) const;
|
||||
vector<GraphicElement> getFrameGraphics() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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)
|
||||
file(MAKE_DIRECTORY ice40/chipdbs/)
|
||||
add_library(ice40_chipdb OBJECT ice40/chipdbs/)
|
||||
|
368
ice40/main.cc
368
ice40/main.cc
@ -16,208 +16,244 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include "design.h"
|
||||
#include "mainwindow.h"
|
||||
#include <QApplication>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "version.h"
|
||||
#include <boost/program_options.hpp>
|
||||
#include "pybindings.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include "design.h"
|
||||
#include "jsonparse.h"
|
||||
#include "mainwindow.h"
|
||||
#include "pybindings.h"
|
||||
#include "version.h"
|
||||
|
||||
void svg_dump_el(const GraphicElement &el)
|
||||
{
|
||||
float scale = 10.0, offset = 10.0;
|
||||
std::string style = "stroke=\"black\" stroke-width=\"0.1\" fill=\"none\"";
|
||||
float scale = 10.0, offset = 10.0;
|
||||
std::string style = "stroke=\"black\" stroke-width=\"0.1\" fill=\"none\"";
|
||||
|
||||
if (el.type == GraphicElement::G_BOX) {
|
||||
std::cout << "<rect x=\"" << (offset + scale*el.x1) << "\" y=\"" << (offset + scale*el.y1) <<
|
||||
"\" height=\"" << (scale*(el.y2-el.y1)) << "\" width=\"" << (scale*(el.x2-el.x1)) << "\" " << style << "/>\n";
|
||||
}
|
||||
if (el.type == GraphicElement::G_BOX) {
|
||||
std::cout << "<rect x=\"" << (offset + scale * el.x1) << "\" y=\""
|
||||
<< (offset + scale * el.y1) << "\" height=\""
|
||||
<< (scale * (el.y2 - el.y1)) << "\" width=\""
|
||||
<< (scale * (el.x2 - el.x1)) << "\" " << style << "/>\n";
|
||||
}
|
||||
|
||||
if (el.type == GraphicElement::G_LINE) {
|
||||
std::cout << "<line x1=\"" << (offset + scale*el.x1) << "\" y1=\"" << (offset + scale*el.y1) <<
|
||||
"\" x2=\"" << (offset + scale*el.x2) << "\" y2=\"" << (offset + scale*el.y2) << "\" " << style << "/>\n";
|
||||
}
|
||||
if (el.type == GraphicElement::G_LINE) {
|
||||
std::cout << "<line x1=\"" << (offset + scale * el.x1) << "\" y1=\""
|
||||
<< (offset + scale * el.y1) << "\" x2=\""
|
||||
<< (offset + scale * el.x2) << "\" y2=\""
|
||||
<< (offset + scale * el.y2) << "\" " << style << "/>\n";
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
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()("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;
|
||||
pos.add("run", -1);
|
||||
|
||||
po::positional_options_description pos;
|
||||
pos.add("file", -1);
|
||||
po::variables_map vm;
|
||||
try {
|
||||
po::parsed_options parsed = po::command_line_parser(argc, argv)
|
||||
.options(options)
|
||||
.positional(pos)
|
||||
.run();
|
||||
|
||||
po::variables_map vm;
|
||||
try {
|
||||
po::parsed_options parsed = po::command_line_parser(argc, argv).
|
||||
options(options).
|
||||
positional(pos).
|
||||
run();
|
||||
po::store(parsed, vm);
|
||||
|
||||
po::store(parsed, vm);
|
||||
|
||||
po::notify(vm);
|
||||
}
|
||||
po::notify(vm);
|
||||
}
|
||||
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cout << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vm.count("help") || argc == 1)
|
||||
{
|
||||
std::cout << basename(argv[0]) << " -- Next Generation Place and Route (git sha1 " GIT_COMMIT_HASH_STR ")\n";
|
||||
std::cout << "\n";
|
||||
std::cout << options << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vm.count("version"))
|
||||
{
|
||||
std::cout << basename(argv[0])
|
||||
<< " -- Next Generation Place and Route (git sha1 "
|
||||
GIT_COMMIT_HASH_STR ")\n";
|
||||
return 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 << "\n";
|
||||
std::cout << options << "\n";
|
||||
return argc != 1;
|
||||
}
|
||||
|
||||
ChipArgs chipArgs;
|
||||
chipArgs.type = ChipArgs::HX1K;
|
||||
if (vm.count("version")) {
|
||||
std::cout << basename(argv[0])
|
||||
<< " -- Next Generation Place and Route (git "
|
||||
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vm.count("lp384"))
|
||||
chipArgs.type = ChipArgs::LP384;
|
||||
ChipArgs chipArgs;
|
||||
|
||||
if (vm.count("lp1k"))
|
||||
chipArgs.type = ChipArgs::LP1K;
|
||||
if (vm.count("lp384")) {
|
||||
if (chipArgs.type != ChipArgs::NONE)
|
||||
goto help;
|
||||
chipArgs.type = ChipArgs::LP384;
|
||||
}
|
||||
|
||||
if (vm.count("lp8k"))
|
||||
chipArgs.type = ChipArgs::LP8K;
|
||||
if (vm.count("lp1k")) {
|
||||
if (chipArgs.type != ChipArgs::NONE)
|
||||
goto help;
|
||||
chipArgs.type = ChipArgs::LP1K;
|
||||
}
|
||||
|
||||
if (vm.count("hx1k"))
|
||||
chipArgs.type = ChipArgs::HX1K;
|
||||
if (vm.count("lp8k")) {
|
||||
if (chipArgs.type != ChipArgs::NONE)
|
||||
goto help;
|
||||
chipArgs.type = ChipArgs::LP8K;
|
||||
}
|
||||
|
||||
if (vm.count("hx8k"))
|
||||
chipArgs.type = ChipArgs::HX8K;
|
||||
if (vm.count("hx1k")) {
|
||||
if (chipArgs.type != ChipArgs::NONE)
|
||||
goto help;
|
||||
chipArgs.type = ChipArgs::HX1K;
|
||||
}
|
||||
|
||||
if (vm.count("up5k"))
|
||||
chipArgs.type = ChipArgs::UP5K;
|
||||
if (vm.count("hx8k")) {
|
||||
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"))
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
if (chipArgs.type == ChipArgs::NONE)
|
||||
chipArgs.type = ChipArgs::HX1K;
|
||||
|
||||
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"))
|
||||
{
|
||||
int bel_count = 0, wire_count = 0, pip_count = 0;
|
||||
Design design(chipArgs);
|
||||
init_python(argv[0]);
|
||||
python_export_global("design", design);
|
||||
|
||||
std::cout << "Checking bel names.\n";
|
||||
for (auto bel : design.chip.getBels()) {
|
||||
auto name = design.chip.getBelName(bel);
|
||||
assert(bel == design.chip.getBelByName(name));
|
||||
bel_count++;
|
||||
}
|
||||
std::cout << " checked " << bel_count << " bels.\n";
|
||||
if (vm.count("test")) {
|
||||
int bel_count = 0, wire_count = 0, pip_count = 0;
|
||||
|
||||
std::cout << "Checking wire names.\n";
|
||||
for (auto wire : design.chip.getWires()) {
|
||||
auto name = design.chip.getWireName(wire);
|
||||
assert(wire == design.chip.getWireByName(name));
|
||||
wire_count++;
|
||||
}
|
||||
std::cout << " checked " << wire_count << " wires.\n";
|
||||
std::cout << "Checking bel names.\n";
|
||||
for (auto bel : design.chip.getBels()) {
|
||||
auto name = design.chip.getBelName(bel);
|
||||
assert(bel == design.chip.getBelByName(name));
|
||||
bel_count++;
|
||||
}
|
||||
std::cout << " checked " << bel_count << " bels.\n";
|
||||
|
||||
std::cout << "Checking pip names.\n";
|
||||
for (auto pip : design.chip.getPips()) {
|
||||
auto name = design.chip.getPipName(pip);
|
||||
assert(pip == design.chip.getPipByName(name));
|
||||
pip_count++;
|
||||
}
|
||||
std::cout << " checked " << pip_count << " pips.\n";
|
||||
std::cout << "Checking wire names.\n";
|
||||
for (auto wire : design.chip.getWires()) {
|
||||
auto name = design.chip.getWireName(wire);
|
||||
assert(wire == design.chip.getWireByName(name));
|
||||
wire_count++;
|
||||
}
|
||||
std::cout << " checked " << wire_count << " wires.\n";
|
||||
|
||||
std::cout << "Checking uphill -> downhill consistency.\n";
|
||||
for (auto dst : design.chip.getWires()) {
|
||||
for (auto uphill_pip : design.chip.getPipsUphill(dst)) {
|
||||
bool found_downhill = false;
|
||||
for (auto downhill_pip : design.chip.getPipsDownhill(design.chip.getPipSrcWire(uphill_pip))) {
|
||||
if (uphill_pip == downhill_pip) {
|
||||
assert(!found_downhill);
|
||||
found_downhill = true;
|
||||
}
|
||||
}
|
||||
assert(found_downhill);
|
||||
}
|
||||
}
|
||||
std::cout << "Checking pip names.\n";
|
||||
for (auto pip : design.chip.getPips()) {
|
||||
auto name = design.chip.getPipName(pip);
|
||||
assert(pip == design.chip.getPipByName(name));
|
||||
pip_count++;
|
||||
}
|
||||
std::cout << " checked " << pip_count << " pips.\n";
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
std::cout << "Checking uphill -> downhill consistency.\n";
|
||||
for (auto dst : design.chip.getWires()) {
|
||||
for (auto uphill_pip : design.chip.getPipsUphill(dst)) {
|
||||
bool found_downhill = false;
|
||||
for (auto downhill_pip : design.chip.getPipsDownhill(
|
||||
design.chip.getPipSrcWire(uphill_pip))) {
|
||||
if (uphill_pip == downhill_pip) {
|
||||
assert(!found_downhill);
|
||||
found_downhill = true;
|
||||
}
|
||||
}
|
||||
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"))
|
||||
{
|
||||
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";
|
||||
}
|
||||
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("file"))
|
||||
{
|
||||
std::string filename = vm["file"].as<std::string>();
|
||||
execute_python_file(argv[0],filename.c_str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (vm.count("svg")) {
|
||||
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")) {
|
||||
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;
|
||||
}
|
||||
|
@ -18,13 +18,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "design.h"
|
||||
#include "chip.h"
|
||||
#include "design.h"
|
||||
|
||||
// include after design.h/chip.h
|
||||
#include "pybindings.h"
|
||||
|
||||
void arch_wrap_python() {
|
||||
class_<ChipArgs>("ChipArgs")
|
||||
.def_readwrite("type", &ChipArgs::type);
|
||||
void arch_wrap_python()
|
||||
{
|
||||
class_<ChipArgs>("ChipArgs").def_readwrite("type", &ChipArgs::type);
|
||||
|
||||
enum_<decltype(std::declval<ChipArgs>().type)>("iCE40Type")
|
||||
.value("NONE", ChipArgs::NONE)
|
||||
|
6
python/dump_design.py
Normal file
6
python/dump_design.py
Normal 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
2
python/functions.py
Normal file
@ -0,0 +1,2 @@
|
||||
def test_function():
|
||||
print("Hello World!")
|
Loading…
Reference in New Issue
Block a user