-
Notifications
You must be signed in to change notification settings - Fork 97
Data Container
The data container is used as a base class for gates, nets, and modules and provides basic functionality to store arbitrary data alongside those netlist components. Hence, all functions presented below are available for gates, nets, and modules.
This mechanism serves two purposes. First, it is where HAL keeps everything a netlist parser read from the HDL file that does not fit into the netlist model itself — most importantly the configuration strings of LUTs and flip-flops, which arrive as generics on the gate instance. Second, it is where you can attach your own findings to netlist elements, so that annotations made during an analysis survive saving and reloading the project.
Each data entry is composed of a data category, a data key, the data type, and the data value itself. The data category is, for example, used to distinguish between data parsed from generics and attributes within an HDL file. A data key uniquely addresses a data entry within its category. Hence, a key may be used once within each category. The data type specifies whether the entry contains an integer number, a float, a string, or something else. The data value finally gives the actual value of the data entry. Note that all four fields are strings — HAL does not interpret the type, it only records it.
In a netlist parsed from Verilog or VHDL, entries typically look like this:
| Category | Key | Type | Value |
|---|---|---|---|
generic |
INIT |
bit_vector |
7F80 |
Data can be added using set_data, which takes the category, key, type, and value. A single entry is read back with get_data, which takes category and key and returns a (type, value) tuple. has_data checks whether an entry exists, and delete_data removes it. To retrieve everything at once, get_data_map returns a dict mapping (category, key) to (type, value).
gate = netlist.get_gate_by_id(3) # get gate with ID 3
gate.set_data("generic", "area", "float", "0.34") # set data for area of gate
gate.set_data("generic", "delay", "float", "1.2") # set data for delay time of gate
all_data = gate.get_data_map() # get a dict from (category, key) to (type, value)
area_data = gate.get_data("generic", "area") # get the tuple ("float", "0.34")
gate.has_data("generic", "area") # returns True
gate.delete_data("generic", "area") # delete the data entry containing the areaInspecting the data map of a gate is often the quickest way to find out what a netlist parser actually extracted:
for (category, key), (data_type, value) in gate.get_data_map().items():
print(f"{category}/{key} ({data_type}) = {value}")On FPGA netlists, the configuration string that determines what a LUT computes is stored here — commonly under category generic and key INIT, though the exact location differs between gate libraries. Rather than hardcoding those strings, read them through Gate.get_init_data, which resolves the correct category and identifier from the gate type's InitComponent, see Gate Type.
gate.get_init_data() # portable: works across gate libraries
gate.get_data("generic", "INIT") # only correct if this library uses generic/INITBe aware that writing to the INIT entry of a LUT changes the Boolean function that gate computes. HAL regenerates the function from the configuration string and caches it until the string changes.
Because data entries are serialized into the project's .hal file, the data container is a convenient place to record intermediate results of an analysis:
for gate in recovered_register:
gate.set_data("analysis", "role", "string", "aes_key_register")Pick a category of your own (rather than generic) so your annotations cannot collide with parsed data. For marking sets of elements that you want to see and manage in the GUI, groupings are usually the better fit; use data entries when you need to attach a value rather than just membership.
- Gate, Net and Module — the classes that inherit this functionality
- Grouping — collecting elements instead of annotating them individually
- Selection Details Widget — where stored data shows up in the GUI