generic: Simple working example
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
6a383cd4c5
commit
32327b761a
@ -155,11 +155,15 @@ template <typename Class, typename FuncT, FuncT fn, typename rv_conv> struct fn_
|
|||||||
using class_type = typename WrapIfNotContext<Class>::maybe_wrapped_t;
|
using class_type = typename WrapIfNotContext<Class>::maybe_wrapped_t;
|
||||||
using conv_result_type = typename rv_conv::ret_type;
|
using conv_result_type = typename rv_conv::ret_type;
|
||||||
|
|
||||||
static conv_result_type wrapped_fn(class_type &cls)
|
static object wrapped_fn(class_type &cls)
|
||||||
{
|
{
|
||||||
Context *ctx = get_ctx<Class>(cls);
|
Context *ctx = get_ctx<Class>(cls);
|
||||||
Class &base = get_base<Class>(cls);
|
Class &base = get_base<Class>(cls);
|
||||||
return rv_conv()(ctx, (base.*fn)());
|
try {
|
||||||
|
return object(rv_conv()(ctx, (base.*fn)()));
|
||||||
|
} catch (bad_wrap &) {
|
||||||
|
return object();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
|
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
|
||||||
@ -172,11 +176,15 @@ template <typename Class, typename FuncT, FuncT fn, typename rv_conv, typename a
|
|||||||
using conv_result_type = typename rv_conv::ret_type;
|
using conv_result_type = typename rv_conv::ret_type;
|
||||||
using conv_arg1_type = typename arg1_conv::arg_type;
|
using conv_arg1_type = typename arg1_conv::arg_type;
|
||||||
|
|
||||||
static conv_result_type wrapped_fn(class_type &cls, conv_arg1_type arg1)
|
static object wrapped_fn(class_type &cls, conv_arg1_type arg1)
|
||||||
{
|
{
|
||||||
Context *ctx = get_ctx<Class>(cls);
|
Context *ctx = get_ctx<Class>(cls);
|
||||||
Class &base = get_base<Class>(cls);
|
Class &base = get_base<Class>(cls);
|
||||||
return rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1)));
|
try {
|
||||||
|
return object(rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1))));
|
||||||
|
} catch (bad_wrap &) {
|
||||||
|
return object();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
|
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
|
||||||
@ -191,11 +199,15 @@ struct fn_wrapper_2a
|
|||||||
using conv_arg1_type = typename arg1_conv::arg_type;
|
using conv_arg1_type = typename arg1_conv::arg_type;
|
||||||
using conv_arg2_type = typename arg2_conv::arg_type;
|
using conv_arg2_type = typename arg2_conv::arg_type;
|
||||||
|
|
||||||
static conv_result_type wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2)
|
static object wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2)
|
||||||
{
|
{
|
||||||
Context *ctx = get_ctx<Class>(cls);
|
Context *ctx = get_ctx<Class>(cls);
|
||||||
Class &base = get_base<Class>(cls);
|
Class &base = get_base<Class>(cls);
|
||||||
return rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2)));
|
try {
|
||||||
|
return object(rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2))));
|
||||||
|
} catch (bad_wrap &) {
|
||||||
|
return object();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
|
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
|
||||||
@ -212,11 +224,16 @@ struct fn_wrapper_3a
|
|||||||
using conv_arg2_type = typename arg2_conv::arg_type;
|
using conv_arg2_type = typename arg2_conv::arg_type;
|
||||||
using conv_arg3_type = typename arg3_conv::arg_type;
|
using conv_arg3_type = typename arg3_conv::arg_type;
|
||||||
|
|
||||||
static conv_result_type wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2, conv_arg3_type arg3)
|
static object wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2, conv_arg3_type arg3)
|
||||||
{
|
{
|
||||||
Context *ctx = get_ctx<Class>(cls);
|
Context *ctx = get_ctx<Class>(cls);
|
||||||
Class &base = get_base<Class>(cls);
|
Class &base = get_base<Class>(cls);
|
||||||
return rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3)));
|
try {
|
||||||
|
return object(
|
||||||
|
rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3))));
|
||||||
|
} catch (bad_wrap &) {
|
||||||
|
return object();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
|
template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); }
|
||||||
|
@ -26,6 +26,14 @@
|
|||||||
#include "pywrappers.h"
|
#include "pywrappers.h"
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
namespace PythonConversion {
|
||||||
|
template <> struct string_converter<const IdString &>
|
||||||
|
{
|
||||||
|
const IdString &from_str(Context *ctx, std::string name) { NPNR_ASSERT_FALSE("unsupported"); }
|
||||||
|
|
||||||
|
std::string to_str(Context *ctx, const IdString &id) { return id.str(ctx); }
|
||||||
|
};
|
||||||
|
} // namespace PythonConversion
|
||||||
|
|
||||||
void arch_wrap_python()
|
void arch_wrap_python()
|
||||||
{
|
{
|
||||||
@ -190,6 +198,7 @@ void arch_wrap_python()
|
|||||||
|
|
||||||
WRAP_MAP_UPTR(CellMap, "IdCellMap");
|
WRAP_MAP_UPTR(CellMap, "IdCellMap");
|
||||||
WRAP_MAP_UPTR(NetMap, "IdNetMap");
|
WRAP_MAP_UPTR(NetMap, "IdNetMap");
|
||||||
|
WRAP_VECTOR(const std::vector<IdString>, conv_to_str<IdString>);
|
||||||
}
|
}
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
1
generic/examples/.gitignore
vendored
Normal file
1
generic/examples/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
blinky.txt
|
11
generic/examples/README.md
Normal file
11
generic/examples/README.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Generic Architecture Example
|
||||||
|
|
||||||
|
This contains a simple, artificial, example of the nextpnr generic API.
|
||||||
|
|
||||||
|
- simple.py procedurally generates a simple FPGA architecture with IO at the edges,
|
||||||
|
logic slices in all other tiles, and interconnect only between adjacent tiles
|
||||||
|
|
||||||
|
- report.py stores design information after place-and-route to blinky.txt in place
|
||||||
|
of real bitstream generation
|
||||||
|
|
||||||
|
- Run blinky.sh to build an example design on the FPGA above
|
13
generic/examples/report.py
Normal file
13
generic/examples/report.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
with open("blinky.txt", "w") as f:
|
||||||
|
for nname, net in ctx.nets:
|
||||||
|
print("# Net %s" % nname, file=f)
|
||||||
|
# FIXME: Pip ordering
|
||||||
|
for wire, pip in net.wires:
|
||||||
|
if pip.pip != "":
|
||||||
|
print("%s" % pip.pip, file=f)
|
||||||
|
print("", file=f)
|
||||||
|
for cname, cell in ctx.cells:
|
||||||
|
print("# Cell %s at %s" % (cname, cell.bel), file=f)
|
||||||
|
for param, val in cell.params:
|
||||||
|
print("%s.%s %s" % (cell.bel, param, val), file=f)
|
||||||
|
print("", file=f)
|
4
generic/examples/simple.sh
Executable file
4
generic/examples/simple.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
set -ex
|
||||||
|
yosys -p "tcl ../synth/synth_generic.tcl 4 blinky.json" blinky.v
|
||||||
|
../../nextpnr-generic --pre-pack simple.py --json blinky.json --post-route report.py
|
@ -1,15 +0,0 @@
|
|||||||
(* blackbox *)
|
|
||||||
module SLICE_LUT4(
|
|
||||||
input I0, I1, I2, I3,
|
|
||||||
input CLK,
|
|
||||||
output Q
|
|
||||||
);
|
|
||||||
parameter INIT = 16'h0000;
|
|
||||||
parameter FF_USED = 1'b0;
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
module top(input a, output q);
|
|
||||||
|
|
||||||
SLICE_LUT4 sl_i(.I0(a), .Q(q));
|
|
||||||
|
|
||||||
endmodule
|
|
@ -49,7 +49,7 @@ po::options_description GenericCommandHandler::getArchOptions()
|
|||||||
return specific;
|
return specific;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericCommandHandler::customBitstream(Context *ctx) { log_error("Here is when bitstream gets created"); }
|
void GenericCommandHandler::customBitstream(Context *ctx) {}
|
||||||
|
|
||||||
std::unique_ptr<Context> GenericCommandHandler::createContext()
|
std::unique_ptr<Context> GenericCommandHandler::createContext()
|
||||||
{
|
{
|
||||||
|
@ -252,7 +252,7 @@ static void pack_io(Context *ctx)
|
|||||||
} else {
|
} else {
|
||||||
// Create a GENERIC_IOB buffer
|
// Create a GENERIC_IOB buffer
|
||||||
std::unique_ptr<CellInfo> ice_cell =
|
std::unique_ptr<CellInfo> ice_cell =
|
||||||
create_generic_cell(ctx, ctx->id("GENERIC_IOB"), ci->name.str(ctx) + "$sb_io");
|
create_generic_cell(ctx, ctx->id("GENERIC_IOB"), ci->name.str(ctx) + "$iob");
|
||||||
nxio_to_iob(ctx, ci, ice_cell.get(), packed_cells);
|
nxio_to_iob(ctx, ci, ice_cell.get(), packed_cells);
|
||||||
new_cells.push_back(std::move(ice_cell));
|
new_cells.push_back(std::move(ice_cell));
|
||||||
iob = new_cells.back().get();
|
iob = new_cells.back().get();
|
||||||
|
@ -14,7 +14,7 @@ yosys memory_map
|
|||||||
yosys opt -full
|
yosys opt -full
|
||||||
yosys techmap -map +/techmap.v
|
yosys techmap -map +/techmap.v
|
||||||
yosys opt -fast
|
yosys opt -fast
|
||||||
yosys abc -lut $LUT_K
|
yosys abc -lut $LUT_K -dress
|
||||||
yosys clean
|
yosys clean
|
||||||
yosys techmap -D LUT_K=$LUT_K -map [file dirname [file normalize $argv0]]/cells_map.v
|
yosys techmap -D LUT_K=$LUT_K -map [file dirname [file normalize $argv0]]/cells_map.v
|
||||||
yosys clean
|
yosys clean
|
||||||
|
Loading…
Reference in New Issue
Block a user