From cf647463e4f11ef972a54cdacd97471cf755c9a7 Mon Sep 17 00:00:00 2001 From: gatecat Date: Sat, 28 Oct 2023 17:09:37 +0200 Subject: [PATCH] himbaechel: Add support for new constants API Signed-off-by: gatecat --- himbaechel/arch.cc | 2 +- himbaechel/arch.h | 4 ++++ himbaechel/chipdb.h | 1 + himbaechel/himbaechel_dbgen/chip.py | 12 ++++++------ himbaechel/himbaechel_helpers.cc | 6 +++++- himbaechel/himbaechel_helpers.h | 3 ++- himbaechel/uarch/example/blinky.v | 2 +- himbaechel/uarch/example/constids.inc | 5 +++++ himbaechel/uarch/example/example.cc | 2 +- himbaechel/uarch/example/example_arch_gen.py | 16 ++++++++++++++++ 10 files changed, 42 insertions(+), 11 deletions(-) diff --git a/himbaechel/arch.cc b/himbaechel/arch.cc index 3c0e2bca..1270934e 100644 --- a/himbaechel/arch.cc +++ b/himbaechel/arch.cc @@ -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 *ptr) { return ptr->get(); } diff --git a/himbaechel/arch.h b/himbaechel/arch.h index 55d709ca..84859086 100644 --- a/himbaechel/arch.h +++ b/himbaechel/arch.h @@ -488,6 +488,10 @@ struct Arch : BaseArch 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 { diff --git a/himbaechel/chipdb.h b/himbaechel/chipdb.h index 0e6d1972..2ac7f60b 100644 --- a/himbaechel/chipdb.h +++ b/himbaechel/chipdb.h @@ -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 pips_uphill; diff --git a/himbaechel/himbaechel_dbgen/chip.py b/himbaechel/himbaechel_dbgen/chip.py index f7e2af3c..e3708107 100644 --- a/himbaechel/himbaechel_dbgen/chip.py +++ b/himbaechel/himbaechel_dbgen/chip.py @@ -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) diff --git a/himbaechel/himbaechel_helpers.cc b/himbaechel/himbaechel_helpers.cc index 4ce478bf..773f7b76 100644 --- a/himbaechel/himbaechel_helpers.cc +++ b/himbaechel/himbaechel_helpers.cc @@ -98,7 +98,8 @@ int HimbaechelHelpers::constrain_cell_pairs(const pool &src_ports, void HimbaechelHelpers::replace_constants(CellTypePort vcc_driver, CellTypePort gnd_driver, const dict &vcc_params, - const dict &gnd_params) + const dict &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); diff --git a/himbaechel/himbaechel_helpers.h b/himbaechel/himbaechel_helpers.h index b2a41b65..369f41dc 100644 --- a/himbaechel/himbaechel_helpers.h +++ b/himbaechel/himbaechel_helpers.h @@ -67,7 +67,8 @@ struct HimbaechelHelpers // Replace constants with given driving cells void replace_constants(CellTypePort vcc_driver, CellTypePort gnd_driver, const dict &vcc_params = {}, - const dict &gnd_params = {}); + const dict &gnd_params = {}, IdString vcc_const_val = IdString(), + IdString gnd_const_val = IdString()); }; NEXTPNR_NAMESPACE_END diff --git a/himbaechel/uarch/example/blinky.v b/himbaechel/uarch/example/blinky.v index e26c2fae..128a63d9 100644 --- a/himbaechel/uarch/example/blinky.v +++ b/himbaechel/uarch/example/blinky.v @@ -11,6 +11,6 @@ always @(posedge clk) else ctr <= ctr + 1'b1; -assign leds = ctr; +assign leds = {4'b1010, ctr[7:4]}; endmodule diff --git a/himbaechel/uarch/example/constids.inc b/himbaechel/uarch/example/constids.inc index b40d5be8..900577e4 100644 --- a/himbaechel/uarch/example/constids.inc +++ b/himbaechel/uarch/example/constids.inc @@ -12,3 +12,8 @@ X(O) X(IOB) X(PAD) X(INIT) + +X(GND) +X(GND_DRV) +X(VCC) +X(VCC_DRV) \ No newline at end of file diff --git a/himbaechel/uarch/example/example.cc b/himbaechel/uarch/example/example.cc index c02280cd..4e8dff4a 100644 --- a/himbaechel/uarch/example/example.cc +++ b/himbaechel/uarch/example/example.cc @@ -63,7 +63,7 @@ struct ExampleImpl : HimbaechelAPI // Replace constants with LUTs const dict vcc_params = {{id_INIT, Property(0xFFFF, 16)}}; const dict 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{{id_LUT4, id_F}}, pool{{id_DFF, id_D}}, 1); log_info("Constrained %d LUTFF pairs.\n", lutffs); diff --git a/himbaechel/uarch/example/example_arch_gen.py b/himbaechel/uarch/example/example_arch_gen.py index 81d5c7dc..d4d0496b 100644 --- a/himbaechel/uarch/example/example_arch_gen.py +++ b/himbaechel/uarch/example/example_arch_gen.py @@ -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):