diff --git a/rdl2ot/src/rdl2ot/opentitan.py b/rdl2ot/src/rdl2ot/opentitan.py index eb526fe..bcbfccd 100644 --- a/rdl2ot/src/rdl2ot/opentitan.py +++ b/rdl2ot/src/rdl2ot/opentitan.py @@ -113,7 +113,7 @@ def needs_we(field: dict) -> bool: RC registers, which should use a read-enable signal (connected to their prim_subreg's we port). """ - return field["reggen_sw_access"] != "RC" and field["sw_writable"] + return field["opentitan"]["reggen_sw_access"] != "RC" and field["sw_writable"] def is_homogeneous(reg: dict) -> bool: diff --git a/rdl2ot/src/rdl2ot/rtl_exporter.py b/rdl2ot/src/rdl2ot/rtl_exporter.py index 7de3424..40d8170 100644 --- a/rdl2ot/src/rdl2ot/rtl_exporter.py +++ b/rdl2ot/src/rdl2ot/rtl_exporter.py @@ -5,11 +5,13 @@ """Export RDL to opentitan RTL.""" import json +from enum import Enum from pathlib import Path from jinja2 import Environment, FileSystemLoader from systemrdl import node from systemrdl.rdltypes import OnReadType +from systemrdl.rdltypes.user_struct import UserStruct from rdl2ot import opentitan @@ -30,14 +32,17 @@ def run(root_node: node.AddrmapNode, out_dir: Path, is_soc: bool = False) -> Non factory = OtInterfaceBuilder() data = factory.parse_soc(root_node) if is_soc else factory.parse_ip_block(root_node) - Path(out_dir / "rdl.json").write_text(json.dumps(data, indent=2), encoding="utf-8") + json_file = Path(out_dir / "rdl.json") + json_file.write_text(json.dumps(data, indent=2), encoding="utf-8") + print(f"Generated {json_file}.") if not is_soc: _export(data, out_dir) return for ip_block in data["devices"]: - _export(ip_block, out_dir) + if ip_block["type"] == "device": + _export(ip_block, out_dir) def _export(ip_block: dict, out_dir: Path) -> None: @@ -45,7 +50,7 @@ def _export(ip_block: dict, out_dir: Path) -> None: env = Environment(loader=file_loader) env.filters["camelcase"] = _camelcase - ip_name = ip_block["ip_name"].lower() + ip_name = ip_block["name"].lower() reg_pkg_tpl = env.get_template("reg_pkg.sv.tpl") stream = reg_pkg_tpl.render(ip_block) path = out_dir / f"{ip_name}_reg_pkg.sv" @@ -55,13 +60,40 @@ def _export(ip_block: dict, out_dir: Path) -> None: reg_top_tpl = env.get_template("reg_top.sv.tpl") for interface in ip_block["interfaces"]: name = "_{}".format(interface["name"].lower()) if "name" in interface else "" - data_ = {"ip_name": ip_name, "interface": interface} + data_ = {"name": ip_name, "interface": interface} stream = reg_top_tpl.render(data_).replace(" \n", "\n") path = out_dir / f"{ip_name}{name}_reg_top.sv" path.open("w").write(stream) print(f"Generated {path}.") +class SigType(Enum): + """Used to give a signal different purposes.""" + + NONE = "None" + PadInOut = "PadInOut" + PadInput = "PadInput" + PadOutput = "PadOutput" + Interrupt = "Interrupt" + + def is_pad(self) -> bool: + """Check whether a signal is a pad.""" + return self in [SigType.PadInOut, SigType.PadInput, SigType.PadOutput] + + def is_interrupt(self) -> bool: + """Check whether a signal is a interrupt.""" + return self in [SigType.Interrupt] + + +class IoCombine(Enum): + """May be used when a signal is a pad.""" + + NONE = "None" + Mux = "Mux" + And = "And" + Or = "Or" + + class OtInterfaceBuilder: """OpenTitan Interface Builder.""" @@ -73,11 +105,33 @@ class OtInterfaceBuilder: any_shadowed_reg: bool = False reg_index: int = 0 + def get_signal(self, sig: node.SignalNode) -> dict: + """Parse a signal and return a dict.""" + obj = {} + obj["name"] = sig.inst_name + kind = sig.get_property("sigtype") + obj["type"] = kind.name + if SigType(kind.name).is_pad(): + obj["width"] = sig.get_property("signalwidth") + if combine := sig.get_property("io_combine"): + obj["combine"] = combine.name + return obj + + def parse_array(self, node_: node.AddressableNode) -> list: + """Parse an array node and return a list of offsets.""" + offsets = [] + if node_.is_array: + offset = node_.raw_address_offset + for _idx in range(node_.array_dimensions[0]): + offsets.append(offset) + offset += node_.array_stride + else: + offsets.append(node_.address_offset) + return offsets + def get_field(self, field: node.FieldNode) -> dict: """Parse a field and return a dictionary.""" - obj = {} - obj["name"] = field.inst_name - obj["type"] = "field" + obj = {"name": field.inst_name, "type": "field", "type_name": field.type_name} obj["desc"] = field.get_property("desc", default="") obj["parent_name"] = field.parent.inst_name obj["lsb"] = field.lsb @@ -104,13 +158,14 @@ def get_field(self, field: node.FieldNode) -> dict: obj["encode"] = encode.type_name obj["async"] = field.get_property("async", default=None) obj["sync"] = field.get_property("sync", default=None) - obj["reggen_sw_access"] = opentitan.get_sw_access_enum(field) + obj["opentitan"] = {"reggen_sw_access": opentitan.get_sw_access_enum(field)} return obj def get_mem(self, mem: node.FieldNode) -> dict: """Parse a memory and return a dictionary representing a window.""" obj = {} obj["name"] = mem.inst_name + obj["type"] = "mem" obj["entries"] = mem.get_property("mementries") obj["sw_writable"] = mem.is_sw_writable obj["sw_readable"] = mem.is_sw_readable @@ -118,15 +173,17 @@ def get_mem(self, mem: node.FieldNode) -> dict: obj["offset"] = mem.address_offset obj["size"] = obj["width"] * obj["entries"] // 8 obj["integrity_bypass"] = mem.get_property("integrity_bypass", default=False) + if udps := self.get_udps(mem): + obj["udps"] = udps + self.all_async_clk &= bool(mem.get_property("async_clk", default=False)) self.num_windows += 1 return obj def get_reg(self, reg: node.RegNode) -> dict: """Parse a register and return a dictionary.""" - obj = {} - obj["name"] = reg.inst_name - obj["type"] = "reg" + obj = {"name": reg.inst_name, "type": "reg", "type_name": reg.type_name} + obj["desc"] = reg.get_property("desc", default="") obj["width"] = reg.get_property("regwidth") obj["hw_readable"] = reg.has_hw_readable obj["hw_writable"] = reg.has_hw_writable @@ -138,23 +195,16 @@ def get_reg(self, reg: node.RegNode) -> dict: obj["shadowed"] = reg.get_property("shadowed", default=False) obj["hwre"] = reg.get_property("hwre", default=False) - obj["offsets"] = [] - if reg.is_array: - obj["is_multireg"] = True - self.num_regs += reg.array_dimensions[0] - offset = reg.raw_address_offset - for _idx in range(reg.array_dimensions[0]): - obj["offsets"].append(offset) - offset += reg.array_stride - else: - self.num_regs += 1 - obj["offsets"].append(reg.address_offset) + obj["offsets"] = self.parse_array(reg) + array_size = len(obj["offsets"]) + self.num_regs += array_size + obj["is_multireg"] = array_size > 1 - obj["fields"] = [] sw_write_en = False msb = 0 reset_val = 0 bitmask = 0 + obj["fields"] = [] for f in reg.fields(): field = self.get_field(f) obj["fields"].append(field) @@ -164,24 +214,25 @@ def get_reg(self, reg: node.RegNode) -> dict: reset_val |= field.get("reset", 0) << field["lsb"] obj["msb"] = msb - obj["permit"] = opentitan.register_permit_mask(obj) obj["sw_write_en"] = sw_write_en obj["bitmask"] = bitmask obj["reset"] = reset_val obj["async"] = False - obj["needs_write_en"] = opentitan.needs_write_en(obj) - obj["needs_read_en"] = opentitan.needs_read_en(obj) - obj["needs_qe"] = opentitan.needs_qe(obj) - obj["needs_int_qe"] = opentitan.needs_int_qe(obj) - obj["fields_no_write_en"] = opentitan.fields_no_write_en(obj) obj["is_multifields"] = len(obj["fields"]) > 1 - obj["is_homogeneous"] = opentitan.is_homogeneous(obj) + obj["opentitan"] = { + "permit": opentitan.register_permit_mask(obj), + "needs_write_en": opentitan.needs_write_en(obj), + "needs_read_en": opentitan.needs_read_en(obj), + "needs_qe": opentitan.needs_qe(obj), + "needs_int_qe": opentitan.needs_int_qe(obj), + "fields_no_write_en": opentitan.fields_no_write_en(obj), + "is_homogeneous": opentitan.is_homogeneous(obj), + } self.any_async_clk |= bool(obj["async_clk"]) self.all_async_clk &= bool(obj["async_clk"]) self.any_shadowed_reg |= bool(obj["shadowed"]) - array_size = len(obj["offsets"]) if bool(obj["async_clk"]): for index in range(array_size): reg_name = reg.inst_name + (f"_{index}" if array_size > 1 else "") @@ -196,6 +247,21 @@ def get_paramesters(self, obj: node.AddrmapNode | node.RegfileNode) -> [dict]: for param in obj.inst.parameters ] + def get_udps(self, obj: node.AddrmapNode | node.RegfileNode) -> [dict]: + """Parse the customs properties and return a list of dictionaries.""" + udps = obj.list_properties(include_native=False) + if len(udps) < 1: + return None + res = {} + for name in udps: + udp = obj.get_property(name) + if isinstance(udp, list) and isinstance(udp[0], UserStruct): + res.update({name: [dict(item.members) for item in udp]}) + else: + res.update({name: udp}) + + return res + def get_interface(self, addrmap: node.AddrmapNode, defalt_name: None | str = None) -> dict: """Parse an interface and return a dictionary.""" self.num_regs = 0 @@ -222,6 +288,9 @@ def get_interface(self, addrmap: node.AddrmapNode, defalt_name: None | str = Non elif isinstance(child, node.MemNode): child_obj = self.get_mem(child) interface["windows"].append(child_obj) + elif isinstance(child, node.SignalNode): + # Ignore: it should have being parsed by `parse_ip_block` + continue else: print(f"WARNING: Unsupported type: {type(child)}, skiping...") continue @@ -257,35 +326,37 @@ def get_interface(self, addrmap: node.AddrmapNode, defalt_name: None | str = Non def parse_ip_block(self, ip_block: node.AddrmapNode) -> dict: """Parse the ip_block node of an IP block and return a dictionary.""" - obj = {} - params = self.get_paramesters(ip_block) - if params: + obj = {"name": ip_block.inst_name, "type": "device", "type_name": ip_block.type_name} + if params := self.get_paramesters(ip_block): obj["parameters"] = params - obj["ip_name"] = ip_block.inst_name - - obj["offsets"] = [] - if ip_block.is_array: - offset = ip_block.raw_address_offset - for _idx in range(ip_block.array_dimensions[0]): - obj["offsets"].append(offset) - offset += ip_block.array_stride - else: - obj["offsets"].append(ip_block.address_offset) + + if udps := self.get_udps(ip_block): + obj["udps"] = udps + + obj["offsets"] = self.parse_array(ip_block) + obj["size"] = ip_block.array_stride if ip_block.is_array else ip_block.size obj["interfaces"] = [] obj["alerts"] = [] + obj["pads"] = [] + obj["interrupts"] = [] for child in ip_block.children(): if isinstance(child, node.AddrmapNode): child_obj = self.get_interface(child, DEFAULT_INTERFACE_NAME) obj["interfaces"].append(child_obj) obj["alerts"].extend(child_obj["alerts"]) + elif isinstance(child, node.SignalNode): + signal = self.get_signal(child) + if SigType(signal["type"]).is_pad(): + obj["pads"].append(signal) + elif SigType(signal["type"]).is_interrupt(): + obj["interrupts"].append(signal) + else: + print(f"WARNING: Unsupported signal type: {signal}.") elif isinstance(child, node.RegNode | node.MemNode | node.RegfileNode): continue else: - print( - f"""Error: Unsupported type: {type(child)}, top level only supports - addrmap and reg components.""" - ) + print(f"ERROR: Unsupported type: {type(child)} in Ip block {ip_block.inst_name}.") raise TypeError # If the ip_block contain imediate registers, use a default interface name @@ -305,7 +376,28 @@ def parse_soc(self, root: node.AddrmapNode) -> dict: print("Error: Top level must be an addrmap") raise TypeError - obj = {"devices": []} + obj = {"name": root.inst_name, "devices": []} for child in root.children(): - obj["devices"].append(self.parse_ip_block(child)) + if isinstance(child, node.AddrmapNode): + obj["devices"].append(self.parse_ip_block(child)) + elif isinstance(child, node.MemNode): + obj["devices"].append(self.get_mem(child)) + else: + print( + f"""Error: Unsupported type: {type(child)}, top level only supports + addrmap and mem components.""" + ) + raise TypeError + + interrupts = [] + for device in obj["devices"]: + if len(device.get("interrupts", [])) == 0: + continue + is_array = len(device["offsets"]) > 0 + for idx, _ in enumerate(device["offsets"]): + suffix = f"_{idx}" if is_array else "" + interrupts.append(device["name"] + suffix) + + if len(interrupts) > 0: + obj["interrupts"] = interrupts return obj diff --git a/rdl2ot/src/templates/reg_pkg.sv.tpl b/rdl2ot/src/templates/reg_pkg.sv.tpl index 38c5adf..9edc396 100644 --- a/rdl2ot/src/templates/reg_pkg.sv.tpl +++ b/rdl2ot/src/templates/reg_pkg.sv.tpl @@ -4,7 +4,7 @@ // // Register Package auto-generated by `rdl2ot` containing data structure -package {{ ip_name }}_reg_pkg; +package {{ name }}_reg_pkg; {%- for item in parameters %} {%- if loop.first %} @@ -33,7 +33,7 @@ package {{ ip_name }}_reg_pkg; {%- for alert in alerts %} Alert{{ alert | camelcase }}Idx = {{ loop.index0 }}{{ "," if not loop.last }} {%- endfor %} - } {{ ip_name | lower }}_alert_idx_t; + } {{ name | lower }}_alert_idx_t; {%- endif %} {%- for interface in interfaces %} @@ -70,7 +70,7 @@ package {{ ip_name }}_reg_pkg; } {{ field.name|lower }}; {%- endif %} {%- endfor %} - } {{ ip_name }}_reg2hw_{{ reg.name|lower }}_{{"m" if reg.is_multireg}}reg_t; + } {{ name }}_reg2hw_{{ reg.name|lower }}_{{"m" if reg.is_multireg}}reg_t; {%- endif %} {%- endfor %} {%- endif %} @@ -97,7 +97,7 @@ package {{ ip_name }}_reg_pkg; {%- endif %} {%- endif %} {%- endfor %} - } {{ ip_name }}_hw2reg_{{ reg.name|lower }}_{{"m" if reg.is_multireg}}reg_t; + } {{ name }}_hw2reg_{{ reg.name|lower }}_{{"m" if reg.is_multireg}}reg_t; {%- endif %} {%- endfor %} {%- endif %} @@ -113,11 +113,11 @@ package {{ ip_name }}_reg_pkg; {%- endif %} {%- set width = reg.fields|length * reg.offsets|length if reg.is_homogeneous and reg.is_multifields else reg.offsets|length %} {%- set bits = " [{}:0]".format(width - 1) if reg.is_multireg %} - {{ ip_name }}_reg2hw_{{ reg.name|lower }}_{{"m" if reg.is_multireg}}reg_t{{ bits }} {{ reg.name|lower }}; + {{ name }}_reg2hw_{{ reg.name|lower }}_{{"m" if reg.is_multireg}}reg_t{{ bits }} {{ reg.name|lower }}; {%- endif %} {%- endfor %} {%- if printed.header %} - } {{ ip_name }}{{interface_name|lower}}_reg2hw_t; + } {{ name }}{{interface_name|lower}}_reg2hw_t; {%- endif %} {%- set printed.header = false %} @@ -131,11 +131,11 @@ package {{ ip_name }}_reg_pkg; {%- endif %} {%- set width = reg.fields|length if reg.is_homogeneous and reg.is_multifields else reg.offsets|length %} {%- set bits = " [{}:0]".format(width - 1) if reg.is_multireg %} - {{ ip_name }}_hw2reg_{{ reg.name|lower }}_{{"m" if reg.is_multireg}}reg_t{{ bits }} {{ reg.name|lower }}; + {{ name }}_hw2reg_{{ reg.name|lower }}_{{"m" if reg.is_multireg}}reg_t{{ bits }} {{ reg.name|lower }}; {%- endif %} {%- endfor %} {%- if printed.header %} - } {{ ip_name }}{{interface_name}}_hw2reg_t; + } {{ name }}{{interface_name}}_hw2reg_t; {%- endif %} {%- set printed.header = false %} @@ -143,7 +143,7 @@ package {{ ip_name }}_reg_pkg; {%- for reg in registers %} {%- for offset in reg.offsets %} {%- set index = "_{}".format(loop.index0) if reg.offsets|length > 1 %} - {%- set offset_name = "{}_{}{}_OFFSET".format(ip_name, reg.name, index)|upper %} + {%- set offset_name = "{}_{}{}_OFFSET".format(name, reg.name, index)|upper %} {%- if not printed.header %} // Register offsets for {{ interface.name|lower}} interface @@ -165,10 +165,10 @@ package {{ ip_name }}_reg_pkg; {%- for offset in reg.offsets %} {%- set index = "_{}".format(loop.index0) if reg.offsets|length > 1 %} {%- set regname = (reg.name ~ index)|upper %} - parameter logic {{ "[{}:0] {}_{}_RESVAL = {}'h {:x}".format(reg.msb, ip_name|upper, regname, reg.msb + 1, reg.reset) }}; + parameter logic {{ "[{}:0] {}_{}_RESVAL = {}'h {:x}".format(reg.msb, name|upper, regname, reg.msb + 1, reg.reset) }}; {%- for field in reg.fields %} {%- if 'reset' in field %} - parameter logic {{ "[{}:0] {}_{}_{}{}_RESVAL = {}'h {:x}".format(field.width - 1, ip_name|upper, regname, field.name|upper, index, field.width, field.reset) }}; + parameter logic {{ "[{}:0] {}_{}_{}{}_RESVAL = {}'h {:x}".format(field.width - 1, name|upper, regname, field.name|upper, index, field.width, field.reset) }}; {%- endif -%} {%- endfor %} {%- endfor %} @@ -180,9 +180,9 @@ package {{ ip_name }}_reg_pkg; // Window parameters for {{ interface.name|lower}} interface {%- for win in interface.windows %} - parameter logic [{{ addr_with_name }}-1:0] {{ ip_name|upper }}_{{ win.name|upper }}_OFFSET = {{ "{}'h {:x}".format(interface.addr_width, win.offset) }}; - parameter int unsigned {{ ip_name|upper }}_{{ win.name|upper }}_SIZE = 'h {{ "{:x}".format(win.size) }}; - parameter int unsigned {{ ip_name|upper }}_{{ win.name|upper }}_IDX = {{ loop.index0 }}; + parameter logic [{{ addr_with_name }}-1:0] {{ name|upper }}_{{ win.name|upper }}_OFFSET = {{ "{}'h {:x}".format(interface.addr_width, win.offset) }}; + parameter int unsigned {{ name|upper }}_{{ win.name|upper }}_SIZE = 'h {{ "{:x}".format(win.size) }}; + parameter int unsigned {{ name|upper }}_{{ win.name|upper }}_IDX = {{ loop.index0 }}; {%- endfor %} {%- endif %} @@ -195,10 +195,10 @@ package {{ ip_name }}_reg_pkg; {%- for offset in reg.offsets %} {%- set index = "_{}".format(loop.index0) if reg.offsets|length > 1 %} {%- set regname = (reg.name ~ index)|upper %} - {{ "{}_{}{}".format(ip_name, regname, "," if not (loop.last and out_loop.last) )|upper }} + {{ "{}_{}{}".format(name, regname, "," if not (loop.last and out_loop.last) )|upper }} {%- endfor %} {%- endfor %} - } {{ ip_name }}{{interface_name}}_id_e; + } {{ name }}{{interface_name}}_id_e; {%- endif %} {%- set ns = namespace(index=0) %} @@ -212,10 +212,10 @@ package {{ ip_name }}_reg_pkg; {%- if not printed.header %} // Register width information to check illegal writes for {{ interface.name|lower}} interface - parameter logic [3:0] {{ (ip_name ~ interface_name)|upper }}_PERMIT [{{ interface.num_regs }}] = '{ + parameter logic [3:0] {{ (name ~ interface_name)|upper }}_PERMIT [{{ interface.num_regs }}] = '{ {%- set printed.header = true %} {%- endif %} - 4'b {{ "{:04b}{} // {} {}_{}{}".format(reg.permit, "," if not (loop.last and out_loop.last) else " ", index, ip_name|upper, regname, suffix) }} + 4'b {{ "{:04b}{} // {} {}_{}{}".format(reg.opentitan.permit, "," if not (loop.last and out_loop.last) else " ", index, name|upper, regname, suffix) }} {%- set ns.index = ns.index + 1 %} {%- endfor %} {%- endfor %} diff --git a/rdl2ot/src/templates/reg_top.sv.tpl b/rdl2ot/src/templates/reg_top.sv.tpl index 3c52a28..f037b17 100644 --- a/rdl2ot/src/templates/reg_top.sv.tpl +++ b/rdl2ot/src/templates/reg_top.sv.tpl @@ -13,7 +13,7 @@ {%- set num_regs_digits = interface.num_regs | string | length %} {%- set clk_name = "aon_" %} -module {{ ip_name|lower }}{{interface_name}}_reg_top ( +module {{ name|lower }}{{interface_name}}_reg_top ( input clk_i, input rst_ni, {%- if interface.any_async_clk %} @@ -36,8 +36,8 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( {%- if has_regs %} // To HW - output {{ ip_name|lower }}_reg_pkg::{{ ip_name|lower }}{{interface_name}}_reg2hw_t reg2hw, // Write - input {{ ip_name|lower }}_reg_pkg::{{ ip_name|lower }}{{interface_name}}_hw2reg_t hw2reg, // Read + output {{ name|lower }}_reg_pkg::{{ name|lower }}{{interface_name}}_reg2hw_t reg2hw, // Write + input {{ name|lower }}_reg_pkg::{{ name|lower }}{{interface_name}}_hw2reg_t hw2reg, // Read {%- endif %} {%- if interface.any_shadowed_reg %} @@ -51,7 +51,7 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( output logic intg_err_o ); - import {{ ip_name|lower }}_reg_pkg::* ; + import {{ name|lower }}_reg_pkg::* ; {%- if interface.needs_aw %} @@ -279,10 +279,10 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( {%- for offset in reg.offsets %} {%- set multireg_idx = loop.index0 %} {%- set reg_suffix = ('_' ~ multireg_idx|string) if reg.offsets|length > 1 %} - {%- if reg.needs_read_en %} + {%- if reg.opentitan.needs_read_en %} logic {{ reg.name|lower }}{{ reg_suffix }}_re; {%- endif %} - {%- if reg.needs_write_en %} + {%- if reg.opentitan.needs_write_en %} logic {{ reg.name|lower }}{{ reg_suffix }}_we; {%- endif %} {%- for field in reg.fields %} @@ -319,13 +319,13 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( {%- set index = ('_' ~ multireg_idx|string) if reg.offsets|length > 1 %} {%- set sig_name = (clk_name ~ reg.name ~ index)|lower %} - {%- set src_we_expr = "{}_we".format(reg.name|lower ~ index) if reg.needs_write_en else "'0" %} - {%- set src_wd_expr = "reg_wdata[{}:0]".format(reg.msb) if reg.needs_write_en else "'0" %} - {%- set src_re_expr = "{}_re".format(reg.name|lower ~ index) if reg.needs_read_en else "'0" %} + {%- set src_we_expr = "{}_we".format(reg.name|lower ~ index) if reg.opentitan.needs_write_en else "'0" %} + {%- set src_wd_expr = "reg_wdata[{}:0]".format(reg.msb) if reg.opentitan.needs_write_en else "'0" %} + {%- set src_re_expr = "{}_re".format(reg.name|lower ~ index) if reg.opentitan.needs_read_en else "'0" %} {%- set src_regwen_expr = "{}_qs".format(reg.fields[0].write_en_signal.parent_name|lower) if reg.sw_write_en else "'0" %} - {%- set dst_we_expr = "{}_we".format(sig_name) if reg.needs_write_en %} - {%- set dst_wd_expr = "{}_wdata".format(sig_name) if reg.needs_write_en %} - {%- set dst_re_expr = "{}_re".format(sig_name) if reg.needs_read_en %} + {%- set dst_we_expr = "{}_we".format(sig_name) if reg.opentitan.needs_write_en %} + {%- set dst_wd_expr = "{}_wdata".format(sig_name) if reg.opentitan.needs_write_en %} + {%- set dst_re_expr = "{}_re".format(sig_name) if reg.opentitan.needs_read_en %} {%- set dst_qe_expr = "{}_qe".format(sig_name) if reg.hw_writable else "'0" %} {%- set dst_wr_req = "1" if reg.hw_writable else "0" %} {%- set dst_ds_expr = "{}_ds".format(sig_name) if reg.hw_writable else "'0" %} @@ -347,12 +347,12 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( logic {{ dst_qe_expr }}; {%- endif %} logic [{{ reg.msb }}:0] {{ sig_name }}_qs; - {%- if reg.needs_write_en %} + {%- if reg.opentitan.needs_write_en %} logic [{{ reg.msb }}:0] {{ sig_name }}_wdata; logic {{ sig_name }}_we; logic unused_{{ sig_name }}_wdata; {%- endif %} - {%- if reg.needs_read_en %} + {%- if reg.opentitan.needs_read_en %} logic {{ dst_re_expr }}; {%- endif %} {%- if reg.sw_write_en %} @@ -403,7 +403,7 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( .dst_regwen_o ({{ dst_regwen_expr }}), .dst_wd_o ({{ dst_wd_expr }}) ); - {%- if reg.needs_write_en %} + {%- if reg.opentitan.needs_write_en %} assign unused_{{ sig_name }}_wdata = ^{{ sig_name }}_wdata; {%- endif %} @@ -431,22 +431,22 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( {%- endif %} {{- space }} // R[{{ regname }}]: V({{ reg.external }}) - {%- if reg.needs_qe %} + {%- if reg.opentitan.needs_qe %} logic {{ regname }}_qe; {%- endif %} - {%- if reg.needs_int_qe %} + {%- if reg.opentitan.needs_int_qe %} logic {{ '[{}:0] {}'.format(reg.fields|length - 1, regname) }}_flds_we; {%- endif %} - {%- if reg.needs_qe %} + {%- if reg.opentitan.needs_qe %} {%- if reg.external %} - {%- if reg.fields_no_write_en > 0 %} + {%- if reg.opentitan.fields_no_write_en > 0 %} // This ignores QEs that are set to constant 0 due to read-only fields. logic unused_{{ reg.name|lower }}_flds_we; - assign unused_{{ reg.name|lower }}_flds_we = {{ "^({}_flds_we & {}'h{:x})".format(reg.name|lower, reg.fields|length, reg.fields_no_write_en ) }}; + assign unused_{{ reg.name|lower }}_flds_we = {{ "^({}_flds_we & {}'h{:x})".format(reg.name|lower, reg.fields|length, reg.opentitan.fields_no_write_en ) }}; {%- endif %} {%- set right_expr = "{}_flds_we".format(regname) %} - {%- set right_expr = right_expr ~ (" | {}'h{:x}".format(reg.fields|length, reg.fields_no_write_en ) if reg.fields_no_write_en > 0) %} - assign {{regname }}_qe = &{{ "({})".format(right_expr) if reg.fields_no_write_en > 0 else "{}".format(right_expr) }}; + {%- set right_expr = right_expr ~ (" | {}'h{:x}".format(reg.fields|length, reg.opentitan.fields_no_write_en ) if reg.opentitan.fields_no_write_en > 0) %} + assign {{regname }}_qe = &{{ "({})".format(right_expr) if reg.opentitan.fields_no_write_en > 0 else "{}".format(right_expr) }}; {%- else %} prim_flop #( .Width(1), @@ -454,7 +454,7 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( ) u_{{ reg.name|lower ~ loop.index0}}_qe ( .clk_i(clk_i), .rst_ni(rst_ni), - .d_i(&({{ regname }}_flds_we {{"| {}'h{:x}".format(reg.fields|length, reg.fields_no_write_en) if reg.fields_no_write_en }})), + .d_i(&({{ regname }}_flds_we {{"| {}'h{:x}".format(reg.fields|length, reg.opentitan.fields_no_write_en) if reg.opentitan.fields_no_write_en }})), .q_o({{ regname }}_qe) ); {%- endif %} @@ -462,7 +462,7 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( {%- if reg.async_clk and reg.hw_writable %} assign {{clk_prefix ~ regname }}_qe = |{{"{}".format(regname) }}_flds_we; {%- endif %} - {%- if reg.sw_write_en and reg.needs_write_en %} + {%- if reg.sw_write_en and reg.opentitan.needs_write_en %} // Create REGWEN-gated WE signal logic {{clk_prefix ~ regname }}_gated_we; {%- set assign.expr = (clk_prefix ~ regname ~ '_we')|lower %} @@ -479,7 +479,7 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( {%- endif %} {%- for field in reg.fields %} {%- set field_name = "_{}{}".format(field.name, multireg_suffix)|lower if reg.is_multifields %} - {%- set property = ".{}".format(field.name)|lower if reg.is_multifields and not reg.is_homogeneous %} + {%- set property = ".{}".format(field.name)|lower if reg.is_multifields and not reg.opentitan.is_homogeneous %} {%- set bit_index = "[{}:{}]".format(field.msb, field.lsb) if field.msb != field.lsb else "[{}]".format(field.msb) %} {%- if reg.is_multifields %} // F{{ '[{}{}]: {}:{}'.format(field.name, multireg_suffix, field.msb, field.lsb)|lower }} @@ -488,7 +488,7 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( .DW ({{ field.width }}) {%- if not reg.external -%} , - .SwAccess(prim_subreg_pkg::SwAccess{{ field.reggen_sw_access }}), + .SwAccess(prim_subreg_pkg::SwAccess{{ field.opentitan.reggen_sw_access }}), .RESVAL ({{ "{}'h{:x}".format(field.width, (field.reset if field.reset else 0)) }}), .Mubi (1'b{{ ("MultiBitBool" in field.encode)|int }}) {%- endif %} @@ -501,7 +501,7 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( {%- endif %} {%- endif %} {{- space }} - {%- set idx = loop.index0 if reg.is_homogeneous and reg.is_multifields else multireg_idx %} + {%- set idx = loop.index0 if reg.opentitan.is_homogeneous and reg.is_multifields else multireg_idx %} {%- set sig_name = (reg.name ~ ("[{}]".format(idx) if reg.is_multireg) ~ property)|lower -%} {%- set suffix = "_int" if reg.async_clk %} {%- if reg.external or reg.shadowed %} @@ -516,7 +516,7 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( {%- if reg.external %} .qre ({{ "reg2hw.{}.re".format(sig_name) if reg.hwre or reg.shadowed }}), {%- endif %} - .qe ({{ "{}_flds_we[{}]".format(regname, loop.index0) if reg.needs_int_qe }}), + .qe ({{ "{}_flds_we[{}]".format(regname, loop.index0) if reg.opentitan.needs_int_qe }}), .q ({{ "reg2hw.{}.q".format(sig_name) if field.hw_readable }}), .ds ({{ "{}{}{}_ds{}".format(clk_prefix, regname, field_name, suffix) if reg.async_clk and reg.hw_writable }}), .qs ({{ "{}{}_qs{}".format(clk_prefix, regname ~ field_name, suffix) if field.sw_readable }}) @@ -555,7 +555,7 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( {%- for offset in reg.offsets %} {%- set index = "{num:>{width}}".format(num=ns.counter, width=num_regs_digits) %} {%- set ns.counter = ns.counter + 1 %} - addr_hit[{{ index }}] = (reg_addr == {{ (ip_name ~ '_' ~ reg.name)|upper }}{% if reg.offsets|length > 1 %}_{{ loop.index0 }}{% endif %}_OFFSET); + addr_hit[{{ index }}] = (reg_addr == {{ (name ~ '_' ~ reg.name)|upper }}{% if reg.offsets|length > 1 %}_{{ loop.index0 }}{% endif %}_OFFSET); {%- endfor %} {%- endfor %} end @@ -573,7 +573,7 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( {%- set index = "{num:>{width}}".format(num=ns.counter, width=num_regs_digits) %} {%- set ns.counter = ns.counter + 1 %} {{"(" if loop.first and outer_loop.first else " " -}} - (addr_hit[{{ index }}] & (|({{ (ip_name ~ interface_name)|upper}}_PERMIT[{{ index }}] & ~reg_be))) + (addr_hit[{{ index }}] & (|({{ (name ~ interface_name)|upper}}_PERMIT[{{ index }}] & ~reg_be))) {%- if loop.last and outer_loop.last %}));{% else %} |{% endif %} {%- endfor %} {%- endfor %} @@ -585,10 +585,10 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( {%- for offset in reg.offsets %} {%- set reg_suffix = ('_' ~ loop.index0|string) if reg.offsets|length > 1 %} {%- set regname = "{}{}".format(reg.name, reg_suffix)|lower %} - {%- if reg.needs_read_en %} + {%- if reg.opentitan.needs_read_en %} assign {{ regname }}_re = addr_hit[{{ ns.re_index }}] & reg_re & !reg_error; {%- endif %} - {%- if reg.needs_write_en %} + {%- if reg.opentitan.needs_write_en %} assign {{ regname }}_we = addr_hit[{{ ns.re_index }}] & reg_we & !reg_error; {%- endif %} {%- set ns.re_index = ns.re_index + 1 %} @@ -610,7 +610,7 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( {%- for reg in registers %} {%- for offset in reg.offsets %} {%- set reg_suffix = ('_' ~ loop.index0|string) if reg.offsets|length > 1 %} - {%- set expr = "{}{}{}_we".format(reg.name, reg_suffix, "_gated" if not reg.async_clk and reg.sw_write_en)|lower if reg.needs_write_en else "1'b0" %} + {%- set expr = "{}{}{}_we".format(reg.name, reg_suffix, "_gated" if not reg.async_clk and reg.sw_write_en)|lower if reg.opentitan.needs_write_en else "1'b0" %} reg_we_check[{{ ns.counter }}] = {{ expr }}; {%- set ns.counter = ns.counter + 1 %} {%- endfor %} @@ -624,7 +624,7 @@ module {{ ip_name|lower }}{{interface_name}}_reg_top ( {%- set ns = namespace(counter=0) %} {%- for reg in registers %} {%- for offset in reg.offsets %} - {%- set reg_suffix = ('_' ~ loop.index0|string) if reg.offsets|length > 1 and not (reg.is_homogeneous and reg.is_multifields) %} + {%- set reg_suffix = ('_' ~ loop.index0|string) if reg.offsets|length > 1 and not (reg.opentitan.is_homogeneous and reg.is_multifields) %} addr_hit[{{ ns.counter }}]: begin {%- set ns.counter = ns.counter + 1 %} {%- if reg.async_clk %}