fuzzers: Add fuzzer for register REGSET and SD
Signed-off-by: David Shah <davey1576@gmail.com>
diff --git a/fuzzers/005-reg_config/empty.ncl b/fuzzers/005-reg_config/empty.ncl
new file mode 100644
index 0000000..b9caf7a
--- /dev/null
+++ b/fuzzers/005-reg_config/empty.ncl
@@ -0,0 +1,12 @@
+::FROM-WRITER;
+design top
+{
+ device
+ {
+ architecture sa5p00;
+ device LFE5U-25F;
+ package CABGA381;
+ performance "8";
+ }
+
+}
diff --git a/fuzzers/005-reg_config/fuzzer.py b/fuzzers/005-reg_config/fuzzer.py
new file mode 100644
index 0000000..3326bab
--- /dev/null
+++ b/fuzzers/005-reg_config/fuzzer.py
@@ -0,0 +1,30 @@
+from fuzzconfig import FuzzConfig
+import nonrouting
+import fuzzloops
+import nets
+import pytrellis
+import re
+
+cfg = FuzzConfig(job="PLC2REG", family="ECP5", device="LFE5U-25F", ncl="empty.ncl", tiles=["R19C33:PLC2"])
+
+
+def main():
+ pytrellis.load_database("../../database")
+ cfg.setup()
+ empty_bitfile = cfg.build_design(cfg.ncl, {})
+ cfg.ncl = "reg.ncl"
+
+ def per_slice(slicen):
+ for r in range(2):
+ def get_substs(regset="RESET", sd="0"):
+ return dict(slice=slicen, r=str(r), regset=regset, sd=sd, gsr="DISABLED")
+
+ nonrouting.fuzz_enum_setting(cfg, "SLICE{}.REG{}.REGSET".format(slicen, r), ["RESET", "SET"], lambda x: get_substs(regset=x),
+ empty_bitfile)
+ nonrouting.fuzz_enum_setting(cfg, "SLICE{}.REG{}.SD".format(slicen, r), ["0", "1"], lambda x: get_substs(sd=x),
+ empty_bitfile)
+ fuzzloops.parallel_foreach(["A", "B", "C", "D"], per_slice)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/fuzzers/005-reg_config/reg.ncl b/fuzzers/005-reg_config/reg.ncl
new file mode 100644
index 0000000..03032dc
--- /dev/null
+++ b/fuzzers/005-reg_config/reg.ncl
@@ -0,0 +1,31 @@
+::FROM-WRITER;
+design top
+{
+ device
+ {
+ architecture sa5p00;
+ device LFE5U-25F;
+ package CABGA381;
+ performance "8";
+ }
+
+ comp SLICE_0
+ {
+ logical
+ {
+ cellmodel-name SLICE;
+ program "MODE:LOGIC "
+ "REG${r}:::REGSET=${regset}:SD=${sd} "
+ "Q${r}:Q "
+ "GSR:${gsr} "
+ "CLKMUX:CLK "
+ "CEMUX:1 "
+ "LSRMUX:LSR "
+ "SRMODE:LSR_OVER_CE "
+ "M0MUX:M0 ";
+ primitive REG${r} q_6;
+ }
+ site R19C33${slice};
+ }
+
+}
diff --git a/libtrellis/include/BitDatabase.hpp b/libtrellis/include/BitDatabase.hpp
index 8a2b9ee..8687240 100644
--- a/libtrellis/include/BitDatabase.hpp
+++ b/libtrellis/include/BitDatabase.hpp
@@ -169,6 +169,10 @@
map<string, BitGroup> options;
boost::optional<string> defval;
+ // Needed for Python
+ void set_defval(string val);
+ string get_defval() const;
+
// Get the value of the enumeration, returning empty if not set or set to default, if default is non-empty
boost::optional<string>
get_value(const CRAMView &tile, boost::optional<BitSet &> coverage = boost::optional<BitSet &>()) const;
diff --git a/libtrellis/src/BitDatabase.cpp b/libtrellis/src/BitDatabase.cpp
index 150e566..472535e 100644
--- a/libtrellis/src/BitDatabase.cpp
+++ b/libtrellis/src/BitDatabase.cpp
@@ -181,6 +181,19 @@
return in;
}
+void EnumSettingBits::set_defval(string val) {
+ defval = val;
+}
+
+
+string EnumSettingBits::get_defval() const {
+ if (defval)
+ return *defval;
+ else
+ return "";
+}
+
+
boost::optional<string> EnumSettingBits::get_value(const CRAMView &tile, boost::optional<BitSet &> coverage) const {
auto found = find_if(options.begin(), options.end(), [tile](const pair<string, BitGroup> &kv) {
return kv.second.match(tile);
diff --git a/libtrellis/src/PyTrellis.cpp b/libtrellis/src/PyTrellis.cpp
index 6e381cc..365a92d 100644
--- a/libtrellis/src/PyTrellis.cpp
+++ b/libtrellis/src/PyTrellis.cpp
@@ -203,7 +203,7 @@
class_<EnumSettingBits>("EnumSettingBits")
.def_readwrite("name", &EnumSettingBits::name)
.def_readwrite("options", &EnumSettingBits::options)
- .def_readwrite("defval", &EnumSettingBits::defval)
+ .add_property("defval", &EnumSettingBits::get_defval, &EnumSettingBits::set_defval)
.def("get_value", &EnumSettingBits::get_value)
.def("set_value", &EnumSettingBits::set_value);
diff --git a/util/fuzz/nonrouting.py b/util/fuzz/nonrouting.py
index 43ea0ca..7101291 100644
--- a/util/fuzz/nonrouting.py
+++ b/util/fuzz/nonrouting.py
@@ -53,3 +53,59 @@
if not is_empty[t]:
tile_dbs[t].add_setting_word(wsb[t])
tile_dbs[t].save()
+
+
+def fuzz_enum_setting(config, name, values, get_ncl_substs, empty_bitfile = None):
+ """
+ Fuzz a setting with multiple possible values
+
+ :param config: FuzzConfig instance containing target device and tile of interest
+ :param name: name of the setting to store in the database
+ :param values: list of values taken by the enum
+ :param get_ncl_substs: a callback function, that is first called with an array of bits to create a design with that setting
+ :param empty_bitfile: a path to a bit file without the parameter included, optional, which is used to determine the
+ default value
+ """
+ prefix = "thread{}_".format(threading.get_ident())
+ tile_dbs = {tile: pytrellis.get_tile_bitdata(
+ pytrellis.TileLocator(config.family, config.device, tiles.type_from_fullname(tile))) for tile in
+ config.tiles}
+ if empty_bitfile is not None:
+ none_chip = pytrellis.Bitstream.read_bit(empty_bitfile).deserialise_chip()
+ else:
+ none_chip = None
+
+ changed_bits = set()
+ chips = {}
+ tiles_changed = set()
+ for val in values:
+ bit_bitf = config.build_design(config.ncl, get_ncl_substs(val), prefix)
+ bit_chip = pytrellis.Bitstream.read_bit(bit_bitf).deserialise_chip()
+ for prev in chips.values():
+ diff = bit_chip - prev
+ for tile in config.tiles:
+ if tile in diff:
+ tiles_changed.add(tile)
+ for bit in diff[tile]:
+ changed_bits.add((tile, bit.frame, bit.bit))
+ chips[val] = bit_chip
+
+ for tile in tiles_changed:
+ esb = pytrellis.EnumSettingBits()
+ esb.name = name
+ for val in values:
+ bg = pytrellis.BitGroup()
+ for (btile, bframe, bbit) in changed_bits:
+ if btile == tile:
+ state = chips[val].tiles[tile].cram.bit(bframe, bbit)
+ cb = pytrellis.ConfigBit()
+ cb.frame = bframe
+ cb.bit = bbit
+ cb.inv = (state == 0)
+ bg.bits.append(cb)
+ esb.options[val] = bg
+ if none_chip is not None and bg.match(none_chip.tiles[tile].cram):
+ esb.defval = val
+ tile_dbs[tile].add_setting_enum(esb)
+ tile_dbs[tile].save()
+