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
|
||||
|
||||
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(); }
|
||||
|
||||
|
@ -488,6 +488,10 @@ struct Arch : BaseArch<ArchRanges>
|
||||
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
|
||||
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); }
|
||||
bool checkWireAvail(WireId wire) const override
|
||||
{
|
||||
|
@ -62,6 +62,7 @@ NPNR_PACKED_STRUCT(struct BelPinRefPOD {
|
||||
NPNR_PACKED_STRUCT(struct TileWireDataPOD {
|
||||
int32_t name;
|
||||
int32_t wire_type;
|
||||
int32_t const_value;
|
||||
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
|
||||
RelSlice<int32_t> pips_uphill;
|
||||
|
@ -144,12 +144,10 @@ class TileWireData:
|
||||
index: int
|
||||
name: IdString
|
||||
wire_type: IdString
|
||||
const_value: IdString = field(default_factory=list)
|
||||
flags: int = 0
|
||||
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
|
||||
pips_uphill: 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):
|
||||
bba.u32(self.name.index)
|
||||
bba.u32(self.wire_type.index)
|
||||
bba.u32(self.const_value.index)
|
||||
bba.u32(self.flags)
|
||||
bba.u32(self.timing_idx)
|
||||
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))
|
||||
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
|
||||
wire = TileWireData(index=len(self.wires),
|
||||
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.wires.append(wire)
|
||||
return wire
|
||||
@ -811,7 +811,7 @@ class Chip:
|
||||
|
||||
bba.label("chip_info")
|
||||
bba.u32(0x00ca7ca7) # magic
|
||||
bba.u32(2) # version
|
||||
bba.u32(3) # version
|
||||
bba.u32(self.width)
|
||||
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,
|
||||
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);
|
||||
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 *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);
|
||||
gnd_drv->connectPort(gnd_driver.port, gnd_net);
|
||||
|
||||
|
@ -67,7 +67,8 @@ struct HimbaechelHelpers
|
||||
// Replace constants with given driving cells
|
||||
void replace_constants(CellTypePort vcc_driver, CellTypePort gnd_driver,
|
||||
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
|
||||
|
@ -11,6 +11,6 @@ always @(posedge clk)
|
||||
else
|
||||
ctr <= ctr + 1'b1;
|
||||
|
||||
assign leds = ctr;
|
||||
assign leds = {4'b1010, ctr[7:4]};
|
||||
|
||||
endmodule
|
||||
|
@ -12,3 +12,8 @@ X(O)
|
||||
X(IOB)
|
||||
X(PAD)
|
||||
X(INIT)
|
||||
|
||||
X(GND)
|
||||
X(GND_DRV)
|
||||
X(VCC)
|
||||
X(VCC_DRV)
|
@ -63,7 +63,7 @@ struct ExampleImpl : HimbaechelAPI
|
||||
// Replace constants with LUTs
|
||||
const dict<IdString, Property> vcc_params = {{id_INIT, Property(0xFFFF, 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
|
||||
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);
|
||||
|
@ -30,6 +30,9 @@ dirs = [ # name, dx, dy
|
||||
|
||||
def create_switch_matrix(tt: TileType, inputs: list[str], outputs: list[str]):
|
||||
# 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
|
||||
for i in range(Wl):
|
||||
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 j in range((i % Sq), Wl, Sq):
|
||||
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
|
||||
for i in range(Wl):
|
||||
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_PREV", "CLK_ROUTE")
|
||||
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
|
||||
|
||||
def is_corner(x, y):
|
||||
|
Loading…
Reference in New Issue
Block a user