diff --git a/lib/1.2/dml-builtins.dml b/lib/1.2/dml-builtins.dml index c7766e97b..44db49cb3 100644 --- a/lib/1.2/dml-builtins.dml +++ b/lib/1.2/dml-builtins.dml @@ -206,6 +206,22 @@ template device { parameter simics_api_version auto; + // see documentation in DML 1.4 + parameter _api_6_or_older = $simics_api_version == "6" + || $simics_api_version == "5" || $simics_api_version == "4.8"; + parameter _compat_proxy_port_ifaces default $_api_6_or_older; + parameter _compat_proxy_port_attrs default $_api_6_or_older; + + // Compatibility proxies are not part of new API versions; thus, the only + // allowed override is from 'true' to 'false' within an old API + // version. + if ($_compat_proxy_port_ifaces && !$_api_6_or_older) { + error; + } + #if ($_compat_proxy_port_attrs && !$_api_6_or_older) { + error; + } + // automatic parameters parameter obj auto; parameter logobj = $obj; diff --git a/lib/1.4/dml-builtins.dml b/lib/1.4/dml-builtins.dml index 806b85e05..d2b7f2129 100644 --- a/lib/1.4/dml-builtins.dml +++ b/lib/1.4/dml-builtins.dml @@ -528,6 +528,25 @@ The `device` template contains the following parameters: this device, as specified by the `--simics-api` command-line argument; e.g. `"6"` for the Simics 6 API. +* `_compat_proxy_port_ifaces`: Version 5 and earlier of Simics relied on + interface ports (as registered by the `SIM_register_port_interface` API + function) for exposing the interfaces of ports and banks. In newer versions + of Simics, interfaces are instead exposed on separate configuration objects. + When this parameter is set to `true`, such ports are registered in addition + to the port objects, for compatibility with scripts written for Simics 5. + For arrays with thousands of ports, this can add a significant compile-time + overhead. The default is `true` if `simics_api_version` parameter is `"6"` or + older. Note that proxy interface ports are not created for all banks and + ports; e.g., banks inside groups or subdevices were not allowed in Simics 5; + therefore there's no old scripts that need the proxies for compatibility. + +* `_compat_proxy_port_attrs`: In Simics 5, configuration attributes for + `connect`, `attribute` and `register` objects inside banks and ports were + register on the device object, named like + bankname_attrname. This parameter controls, in + a similar to the `_compat_proxy_port_ifaces` parameter, whether such proxy + attribute should be created for compatibility. The default is `true` if the + `simics_api_version` parameter is `"6"` or older. */ template device { is object; @@ -539,6 +558,22 @@ template device { param objtype = "device"; param simics_api_version auto; + param _api_5_or_older = simics_api_version == "5" + || simics_api_version == "4.8"; + param _api_6_or_older = simics_api_version == "6" || _api_5_or_older; + + param _compat_proxy_port_ifaces default _api_6_or_older; + param _compat_proxy_port_attrs default _api_6_or_older; + + // Compatibility proxies are not part of new API versions; thus, the only + // allowed override is from 'true' to 'false' within an old API + // version. + #if (_compat_proxy_port_ifaces && !_api_6_or_older) { + error; + } + #if (_compat_proxy_port_attrs && !_api_6_or_older) { + error; + } // automatic parameters param obj auto; @@ -551,8 +586,7 @@ template device { param be_bitorder default _be_bitorder; param log_group = undefined; - param use_io_memory default simics_api_version == "6" - || simics_api_version == "5" || simics_api_version == "4.8"; + param use_io_memory default _api_6_or_older; // this was available in DML 1.2; defensively reserved in 1.4 param banks = undefined; // this carried semantics in DML 1.2; deprecated in 1.4 @@ -1437,8 +1471,7 @@ template port is object { param objtype = "port"; // limitations for ports are not recognized param limitations = undefined; - param obj = (simics_api_version == "5" || simics_api_version == "4.8") - #? dev.obj #: _port_obj(); + param obj = dev._api_5_or_older #? dev.obj #: _port_obj(); session conf_object_t *_cached_port_obj; shared method _port_obj() -> (conf_object_t *) { @@ -1768,8 +1801,7 @@ template bank is (object, shown_desc) { // compatibility: referencing 'obj' in a bank method must evaluate to // dev.obj in code that can compile on both 5 and 6 // TODO: we should probably make obj an immutable session variable - param obj = (simics_api_version == "5" || simics_api_version == "4.8") - #? dev.obj #: _bank_obj(); + param obj = dev._api_5_or_older #? dev.obj #: _bank_obj(); param partial : bool; param overlapping : bool; param _le_byte_order : bool; diff --git a/py/dml/c_backend.py b/py/dml/c_backend.py index 44be699a7..3d6a00873 100644 --- a/py/dml/c_backend.py +++ b/py/dml/c_backend.py @@ -15,7 +15,7 @@ from . import objects, logging, crep, output, ctree, serialize, structure from . import traits import dml.globals -from .structure import get_attr_name, port_class_ident, port_should_get_proxies +from .structure import get_attr_name, port_class_ident, need_port_proxy_attrs from .logging import * from .messages import * from .output import * @@ -510,7 +510,7 @@ def check_attribute(node, port, prefix): report(WNDOC(node, node.logname())) attrname = get_attr_name(prefix, node) register_attribute(node.site, port, attrname) - if port and port_should_get_proxies(port): + if port and need_port_proxy_attrs(port): register_attribute(node.site, None, "%s_%s" % (port.name, attrname)) # dimsizes, loopvars, prefix are relative to port. @@ -580,32 +580,37 @@ def generate_attribute_common(initcode, node, port, dimsizes, prefix, register_attribute(node.site, port, attrname) if port: - if port.dimensions == 0 and port.objtype in {'port', 'bank'}: - register_attribute(node.site, None, "%s_%s" % (port.name, attrname)) - initcode.out( - '_register_port_attr(class, %s, offsetof(%s, %s), %s,' - % (port_class_ident(port), - crep.structtype(dml.globals.device), - crep.cref_portobj(port, ()), - 'true' if port.objtype == "bank" else 'false') - + ' "%s", "%s", %s, %s, %s, "%s", %s);\n' - % (port.name, attrname, getter, setter, - attr_flag, attr_type, doc.read())) - elif port.dimensions == 1 and port.objtype in {'port', 'bank'}: - # Generate an accessor attribute for legacy reasons - register_attribute(node.site, None, "%s_%s" % (port.name, attrname)) - member = crep.cref_portobj( - port, (mkLit(port.site, '0', TInt(32, False)),)) - (dimsize,) = port.dimsizes - initcode.out( - '_register_port_array_attr(class, %s, offsetof(%s, %s),' - % (port_class_ident(port), - crep.structtype(dml.globals.device), - member) - + ' %d, %s, "%s", "%s", %s, %s, %s, "%s",' - % (dimsize, 'true' if port.objtype == "bank" else 'false', - port.name, attrname, getter, setter, attr_flag, attr_type) - + ' %s);\n' % (doc.read(),)) + if need_port_proxy_attrs(port): + if port.dimensions == 0: + register_attribute( + node.site, None, "%s_%s" % (port.name, attrname)) + initcode.out( + '_register_port_attr(class, %s, offsetof(%s, %s), %s,' + % (port_class_ident(port), + crep.structtype(dml.globals.device), + crep.cref_portobj(port, ()), + 'true' if port.objtype == "bank" else 'false') + + ' "%s", "%s", %s, %s, %s, "%s", %s);\n' + % (port.name, attrname, getter, setter, + attr_flag, attr_type, doc.read())) + else: + assert port.dimensions == 1 + # Generate an accessor attribute for legacy reasons + register_attribute( + node.site, None, "%s_%s" % (port.name, attrname)) + member = crep.cref_portobj( + port, (mkLit(port.site, '0', TInt(32, False)),)) + (dimsize,) = port.dimsizes + initcode.out( + '_register_port_array_attr(class, %s, offsetof(%s, %s),' + % (port_class_ident(port), + crep.structtype(dml.globals.device), + member) + + ' %d, %s, "%s", "%s", %s, %s, %s, "%s",' + % (dimsize, 'true' if port.objtype == "bank" else 'false', + port.name, attrname, getter, setter, attr_flag, + attr_type) + + ' %s);\n' % (doc.read(),)) else: initcode.out( '_register_port_attr_no_aux(%s,' @@ -613,7 +618,6 @@ def generate_attribute_common(initcode, node, port, dimsizes, prefix, % (port_class_ident(port), attrname, getter, setter, attr_flag, attr_type, doc.read())) - else: initcode.out('SIM_register_typed_attribute(class, "'+attrname+'",'+ '\n '+ @@ -882,36 +886,37 @@ def generate_implement(code, device, impl): # Legacy interface ports are only added for ports and banks that were # available in Simics 5, i.e. zero or one dimensional direct # descendants of the device object - if (port.local_dimensions() == 0 and port.parent.parent is None - and port.objtype != 'subdevice'): - code.out("static const %s = %s;\n" % ( - ifacetype.declaration('port_iface'), - interface_block(device, ifacestruct, methods, ()))) - code.out('SIM_register_port_interface' - '(class, "%s", &port_iface, "%s", %s);\n' - % (impl.name, crep.cname(port), desc)) - elif (port.local_dimensions() == 1 and port.parent.parent is None - and port.objtype != 'subdevice'): - [arrlen] = port.arraylens() - code.out("static const %s%s = %s;\n" % - (ifacetype.declaration("ifaces"), - "[%s]" % (arrlen,), - "{%s\n}" % ",\n".join( - "%s" % interface_block(device, ifacestruct, - methods, (i, )) - for i in range(arrlen)))) - code.out("interface_array_t iface_vect = VNULL;\n") - idxvar = "i0" - code.out("for (int %s = 0; %s < %d; %s++)\n" % - (idxvar, idxvar, arrlen, idxvar), - postindent = 1) - access = "[%s]" % idxvar - code.out("VADD(iface_vect, &ifaces%s);\n" % access, - postindent = -1) - code.out('VT_register_port_array_interface' - '(class, "%s", &iface_vect, "%s", %s);\n' - % (impl.name, crep.cname(port), desc)) - code.out('VFREE(iface_vect);\n') + if (port.parent is dml.globals.device + and port.objtype in {'port', 'bank'} + and param_bool(dml.globals.device, '_compat_proxy_port_ifaces')): + if port.local_dimensions() == 0: + code.out("static const %s = %s;\n" % ( + ifacetype.declaration('port_iface'), + interface_block(device, ifacestruct, methods, ()))) + code.out('SIM_register_port_interface' + '(class, "%s", &port_iface, "%s", %s);\n' + % (impl.name, crep.cname(port), desc)) + elif port.local_dimensions() == 1: + [arrlen] = port.arraylens() + code.out("static const %s%s = %s;\n" % + (ifacetype.declaration("ifaces"), + "[%s]" % (arrlen,), + "{%s\n}" % ",\n".join( + "%s" % interface_block(device, ifacestruct, + methods, (i, )) + for i in range(arrlen)))) + code.out("interface_array_t iface_vect = VNULL;\n") + idxvar = "i0" + code.out("for (int %s = 0; %s < %d; %s++)\n" % + (idxvar, idxvar, arrlen, idxvar), + postindent = 1) + access = "[%s]" % idxvar + code.out("VADD(iface_vect, &ifaces%s);\n" % access, + postindent = -1) + code.out('VT_register_port_array_interface' + '(class, "%s", &iface_vect, "%s", %s);\n' + % (impl.name, crep.cname(port), desc)) + code.out('VFREE(iface_vect);\n') code.out("}\n", preindent = -1) def port_prefix(port): diff --git a/py/dml/structure.py b/py/dml/structure.py index 3236bc1d3..77533ba84 100644 --- a/py/dml/structure.py +++ b/py/dml/structure.py @@ -2598,11 +2598,12 @@ def mkexpr(self, indices): self.cached = mkLit(self.site, lit, TPtr(TPtr(TNamed('conf_class_t')))) return self.cached -def port_should_get_proxies(port): +def need_port_proxy_attrs(port): assert port.objtype in {'port', 'bank', 'subdevice'} return (port.objtype in {'port', 'bank'} and port.dimensions <= 1 - and port.parent is dml.globals.device) + and port.parent is dml.globals.device + and attr_bool(dml.globals.device, '_compat_proxy_port_attrs')) class ConfAttrParentObjectProxyInfoParamExpr(objects.ParamExpr): '''The _parent_obj_proxy_info parameter of a attribute, register, or @@ -2622,7 +2623,7 @@ def mkexpr(self, indices): return self.cached object_parent = self.node.object_parent if (object_parent is not dml.globals.device - and port_should_get_proxies(object_parent)): + and need_port_proxy_attrs(object_parent)): is_bank = 'true' if object_parent.objtype == 'bank' else 'false' is_array = 'true' if object_parent.dimensions == 1 else 'false' indices = ((mkLit(self.site, '0', TInt(32, False)),)