himbaechel: Add support for new constants API
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
fe52840054
commit
cf647463e4
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
static constexpr int database_version = 2;
|
static constexpr int database_version = 3;
|
||||||
|
|
||||||
static const ChipInfoPOD *get_chip_info(const RelPtr<ChipInfoPOD> *ptr) { return ptr->get(); }
|
static const ChipInfoPOD *get_chip_info(const RelPtr<ChipInfoPOD> *ptr) { return ptr->get(); }
|
||||||
|
|
||||||
|
@ -488,6 +488,10 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
IdString getWireType(WireId wire) const override { return IdString(chip_wire_info(chip_info, wire).wire_type); }
|
IdString getWireType(WireId wire) const override { return IdString(chip_wire_info(chip_info, wire).wire_type); }
|
||||||
DelayQuad getWireDelay(WireId wire) const override { return DelayQuad(0); } // TODO
|
DelayQuad getWireDelay(WireId wire) const override { return DelayQuad(0); } // TODO
|
||||||
BelPinRange getWireBelPins(WireId wire) const override { return BelPinRange(chip_info, get_tile_wire_range(wire)); }
|
BelPinRange getWireBelPins(WireId wire) const override { return BelPinRange(chip_info, get_tile_wire_range(wire)); }
|
||||||
|
IdString getWireConstantValue(WireId wire) const override
|
||||||
|
{
|
||||||
|
return IdString(chip_wire_info(chip_info, wire).const_value);
|
||||||
|
}
|
||||||
WireRange getWires() const override { return WireRange(chip_info); }
|
WireRange getWires() const override { return WireRange(chip_info); }
|
||||||
bool checkWireAvail(WireId wire) const override
|
bool checkWireAvail(WireId wire) const override
|
||||||
{
|
{
|
||||||
|
@ -62,6 +62,7 @@ NPNR_PACKED_STRUCT(struct BelPinRefPOD {
|
|||||||
NPNR_PACKED_STRUCT(struct TileWireDataPOD {
|
NPNR_PACKED_STRUCT(struct TileWireDataPOD {
|
||||||
int32_t name;
|
int32_t name;
|
||||||
int32_t wire_type;
|
int32_t wire_type;
|
||||||
|
int32_t const_value;
|
||||||
int32_t flags; // 32 bits of arbitrary data
|
int32_t flags; // 32 bits of arbitrary data
|
||||||
int32_t timing_idx; // used only when the wire is not part of a node, otherwise node idx applies
|
int32_t timing_idx; // used only when the wire is not part of a node, otherwise node idx applies
|
||||||
RelSlice<int32_t> pips_uphill;
|
RelSlice<int32_t> pips_uphill;
|
||||||
|
@ -144,12 +144,10 @@ class TileWireData:
|
|||||||
index: int
|
index: int
|
||||||
name: IdString
|
name: IdString
|
||||||
wire_type: IdString
|
wire_type: IdString
|
||||||
|
const_value: IdString = field(default_factory=list)
|
||||||
flags: int = 0
|
flags: int = 0
|
||||||
timing_idx: int = -1
|
timing_idx: int = -1
|
||||||
|
|
||||||
# not serialised, but used to build the global constant networks
|
|
||||||
const_val: int = -1
|
|
||||||
|
|
||||||
# these crossreferences will be updated by finalise(), no need to manually update
|
# these crossreferences will be updated by finalise(), no need to manually update
|
||||||
pips_uphill: list[int] = field(default_factory=list)
|
pips_uphill: list[int] = field(default_factory=list)
|
||||||
pips_downhill: list[int] = field(default_factory=list)
|
pips_downhill: list[int] = field(default_factory=list)
|
||||||
@ -168,6 +166,7 @@ class TileWireData:
|
|||||||
def serialise(self, context: str, bba: BBAWriter):
|
def serialise(self, context: str, bba: BBAWriter):
|
||||||
bba.u32(self.name.index)
|
bba.u32(self.name.index)
|
||||||
bba.u32(self.wire_type.index)
|
bba.u32(self.wire_type.index)
|
||||||
|
bba.u32(self.const_value.index)
|
||||||
bba.u32(self.flags)
|
bba.u32(self.flags)
|
||||||
bba.u32(self.timing_idx)
|
bba.u32(self.timing_idx)
|
||||||
bba.slice(f"{context}_pips_uh", len(self.pips_uphill))
|
bba.slice(f"{context}_pips_uh", len(self.pips_uphill))
|
||||||
@ -228,11 +227,12 @@ class TileType(BBAStruct):
|
|||||||
bel.pins.append(BelPin(pin_id, wire_idx, dir))
|
bel.pins.append(BelPin(pin_id, wire_idx, dir))
|
||||||
self.wires[wire_idx].bel_pins.append(BelPinRef(bel.index, pin_id))
|
self.wires[wire_idx].bel_pins.append(BelPinRef(bel.index, pin_id))
|
||||||
|
|
||||||
def create_wire(self, name: str, type: str=""):
|
def create_wire(self, name: str, type: str="", const_value: str=""):
|
||||||
# Create a new tile wire of a given name and type (optional) in the tile type
|
# Create a new tile wire of a given name and type (optional) in the tile type
|
||||||
wire = TileWireData(index=len(self.wires),
|
wire = TileWireData(index=len(self.wires),
|
||||||
name=self.strs.id(name),
|
name=self.strs.id(name),
|
||||||
wire_type=self.strs.id(type))
|
wire_type=self.strs.id(type),
|
||||||
|
const_value=self.strs.id(const_value))
|
||||||
self._wire2idx[wire.name] = wire.index
|
self._wire2idx[wire.name] = wire.index
|
||||||
self.wires.append(wire)
|
self.wires.append(wire)
|
||||||
return wire
|
return wire
|
||||||
@ -811,7 +811,7 @@ class Chip:
|
|||||||
|
|
||||||
bba.label("chip_info")
|
bba.label("chip_info")
|
||||||
bba.u32(0x00ca7ca7) # magic
|
bba.u32(0x00ca7ca7) # magic
|
||||||
bba.u32(2) # version
|
bba.u32(3) # version
|
||||||
bba.u32(self.width)
|
bba.u32(self.width)
|
||||||
bba.u32(self.height)
|
bba.u32(self.height)
|
||||||
|
|
||||||
|
@ -98,7 +98,8 @@ int HimbaechelHelpers::constrain_cell_pairs(const pool<CellTypePort> &src_ports,
|
|||||||
|
|
||||||
void HimbaechelHelpers::replace_constants(CellTypePort vcc_driver, CellTypePort gnd_driver,
|
void HimbaechelHelpers::replace_constants(CellTypePort vcc_driver, CellTypePort gnd_driver,
|
||||||
const dict<IdString, Property> &vcc_params,
|
const dict<IdString, Property> &vcc_params,
|
||||||
const dict<IdString, Property> &gnd_params)
|
const dict<IdString, Property> &gnd_params, IdString vcc_const_val,
|
||||||
|
IdString gnd_const_val)
|
||||||
{
|
{
|
||||||
CellInfo *vcc_drv = ctx->createCell(ctx->id("$PACKER_VCC_DRV"), vcc_driver.cell_type);
|
CellInfo *vcc_drv = ctx->createCell(ctx->id("$PACKER_VCC_DRV"), vcc_driver.cell_type);
|
||||||
vcc_drv->addOutput(vcc_driver.port);
|
vcc_drv->addOutput(vcc_driver.port);
|
||||||
@ -113,6 +114,9 @@ void HimbaechelHelpers::replace_constants(CellTypePort vcc_driver, CellTypePort
|
|||||||
NetInfo *vcc_net = ctx->createNet(ctx->id("$PACKER_VCC"));
|
NetInfo *vcc_net = ctx->createNet(ctx->id("$PACKER_VCC"));
|
||||||
NetInfo *gnd_net = ctx->createNet(ctx->id("$PACKER_GND"));
|
NetInfo *gnd_net = ctx->createNet(ctx->id("$PACKER_GND"));
|
||||||
|
|
||||||
|
vcc_net->constant_value = vcc_const_val;
|
||||||
|
gnd_net->constant_value = gnd_const_val;
|
||||||
|
|
||||||
vcc_drv->connectPort(vcc_driver.port, vcc_net);
|
vcc_drv->connectPort(vcc_driver.port, vcc_net);
|
||||||
gnd_drv->connectPort(gnd_driver.port, gnd_net);
|
gnd_drv->connectPort(gnd_driver.port, gnd_net);
|
||||||
|
|
||||||
|
@ -67,7 +67,8 @@ struct HimbaechelHelpers
|
|||||||
// Replace constants with given driving cells
|
// Replace constants with given driving cells
|
||||||
void replace_constants(CellTypePort vcc_driver, CellTypePort gnd_driver,
|
void replace_constants(CellTypePort vcc_driver, CellTypePort gnd_driver,
|
||||||
const dict<IdString, Property> &vcc_params = {},
|
const dict<IdString, Property> &vcc_params = {},
|
||||||
const dict<IdString, Property> &gnd_params = {});
|
const dict<IdString, Property> &gnd_params = {}, IdString vcc_const_val = IdString(),
|
||||||
|
IdString gnd_const_val = IdString());
|
||||||
};
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -11,6 +11,6 @@ always @(posedge clk)
|
|||||||
else
|
else
|
||||||
ctr <= ctr + 1'b1;
|
ctr <= ctr + 1'b1;
|
||||||
|
|
||||||
assign leds = ctr;
|
assign leds = {4'b1010, ctr[7:4]};
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -12,3 +12,8 @@ X(O)
|
|||||||
X(IOB)
|
X(IOB)
|
||||||
X(PAD)
|
X(PAD)
|
||||||
X(INIT)
|
X(INIT)
|
||||||
|
|
||||||
|
X(GND)
|
||||||
|
X(GND_DRV)
|
||||||
|
X(VCC)
|
||||||
|
X(VCC_DRV)
|
@ -63,7 +63,7 @@ struct ExampleImpl : HimbaechelAPI
|
|||||||
// Replace constants with LUTs
|
// Replace constants with LUTs
|
||||||
const dict<IdString, Property> vcc_params = {{id_INIT, Property(0xFFFF, 16)}};
|
const dict<IdString, Property> vcc_params = {{id_INIT, Property(0xFFFF, 16)}};
|
||||||
const dict<IdString, Property> gnd_params = {{id_INIT, Property(0x0000, 16)}};
|
const dict<IdString, Property> gnd_params = {{id_INIT, Property(0x0000, 16)}};
|
||||||
h.replace_constants(CellTypePort(id_LUT4, id_F), CellTypePort(id_LUT4, id_F), vcc_params, gnd_params);
|
h.replace_constants(CellTypePort(id_VCC_DRV, id_VCC), CellTypePort(id_GND_DRV, id_GND), {}, {}, id_VCC, id_GND);
|
||||||
// Constrain directly connected LUTs and FFs together to use dedicated resources
|
// Constrain directly connected LUTs and FFs together to use dedicated resources
|
||||||
int lutffs = h.constrain_cell_pairs(pool<CellTypePort>{{id_LUT4, id_F}}, pool<CellTypePort>{{id_DFF, id_D}}, 1);
|
int lutffs = h.constrain_cell_pairs(pool<CellTypePort>{{id_LUT4, id_F}}, pool<CellTypePort>{{id_DFF, id_D}}, 1);
|
||||||
log_info("Constrained %d LUTFF pairs.\n", lutffs);
|
log_info("Constrained %d LUTFF pairs.\n", lutffs);
|
||||||
|
@ -30,6 +30,9 @@ dirs = [ # name, dx, dy
|
|||||||
|
|
||||||
def create_switch_matrix(tt: TileType, inputs: list[str], outputs: list[str]):
|
def create_switch_matrix(tt: TileType, inputs: list[str], outputs: list[str]):
|
||||||
# FIXME: terrible routing matrix, just for a toy example...
|
# FIXME: terrible routing matrix, just for a toy example...
|
||||||
|
# constant wires
|
||||||
|
tt.create_wire("GND", "GND", const_value="GND")
|
||||||
|
tt.create_wire("VCC", "VCC", const_value="VCC")
|
||||||
# switch wires
|
# switch wires
|
||||||
for i in range(Wl):
|
for i in range(Wl):
|
||||||
tt.create_wire(f"SWITCH{i}", "SWITCH")
|
tt.create_wire(f"SWITCH{i}", "SWITCH")
|
||||||
@ -45,6 +48,10 @@ def create_switch_matrix(tt: TileType, inputs: list[str], outputs: list[str]):
|
|||||||
for i, w in enumerate(outputs):
|
for i, w in enumerate(outputs):
|
||||||
for j in range((i % Sq), Wl, Sq):
|
for j in range((i % Sq), Wl, Sq):
|
||||||
tt.create_pip(w, f"SWITCH{j}", timing_class="SWINPUT")
|
tt.create_pip(w, f"SWITCH{j}", timing_class="SWINPUT")
|
||||||
|
# constant pips
|
||||||
|
for i in range(Wl):
|
||||||
|
tt.create_pip("GND", f"SWITCH{i}")
|
||||||
|
tt.create_pip("VCC", f"SWITCH{i}")
|
||||||
# neighbour local pips
|
# neighbour local pips
|
||||||
for i in range(Wl):
|
for i in range(Wl):
|
||||||
for j, (d, dx, dy) in enumerate(dirs):
|
for j, (d, dx, dy) in enumerate(dirs):
|
||||||
@ -147,6 +154,15 @@ def create_corner_tiletype(ch):
|
|||||||
tt.create_wire(f"CLK", "TILE_CLK")
|
tt.create_wire(f"CLK", "TILE_CLK")
|
||||||
tt.create_wire(f"CLK_PREV", "CLK_ROUTE")
|
tt.create_wire(f"CLK_PREV", "CLK_ROUTE")
|
||||||
tt.create_pip(f"CLK_PREV", f"CLK")
|
tt.create_pip(f"CLK_PREV", f"CLK")
|
||||||
|
|
||||||
|
tt.create_wire(f"GND", "GND", const_value="GND")
|
||||||
|
tt.create_wire(f"VCC", "VCC", const_value="VCC")
|
||||||
|
|
||||||
|
gnd = tt.create_bel(f"GND_DRV", f"GND_DRV", z=0)
|
||||||
|
tt.add_bel_pin(gnd, "GND", "GND", PinType.OUTPUT)
|
||||||
|
vcc = tt.create_bel(f"VCC_DRV", f"VCC_DRV", z=1)
|
||||||
|
tt.add_bel_pin(vcc, "VCC", "VCC", PinType.OUTPUT)
|
||||||
|
|
||||||
return tt
|
return tt
|
||||||
|
|
||||||
def is_corner(x, y):
|
def is_corner(x, y):
|
||||||
|
Loading…
Reference in New Issue
Block a user