Skip to content

Commit 013ea05

Browse files
committed
Fix logging always using the device object within shared methods -- SIMICS-11346
1 parent 407f9d9 commit 013ea05

17 files changed

+191
-84
lines changed

RELEASENOTES-1.4.docu

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,4 +513,9 @@
513513
within a port, bank or subdevice that is itself declared within an object
514514
array would lead to the type of that attribute being incorrectly
515515
registered <bug number="SIMICS-21474"/>.</add-note></build-id>
516+
<build-id value="next"><add-note> Fixed a bug where log statements within
517+
<tt>shared</tt> methods would always use the device's configuration object
518+
as the log object instead of the configuration object of the nearest
519+
enclosing <tt>device</tt>, <tt>port</tt>, <tt>bank</tt> or
520+
<tt>subdevice</tt> <bug number="SIMICS-11346"/>.
516521
</rn>

include/simics/dmllib.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3130,10 +3130,24 @@ _DML_get_single_hook_attr(void *_hook, uintptr_t _aux) {
31303130
}
31313131

31323132

3133-
UNUSED static uint64 _identity_to_key(_identity_t id) {
3133+
UNUSED static inline uint64 _identity_to_key(_identity_t id) {
31343134
return (uint64)id.id << 32 | (uint64)id.encoded_index;
31353135
}
31363136

3137+
typedef struct {
3138+
uint32 port_obj_offset;
3139+
uint32 index_divisor;
3140+
} _dml_log_object_assoc_t;
3141+
3142+
UNUSED static inline conf_object_t *
3143+
_identity_to_logobj(const _dml_log_object_assoc_t *object_assocs,
3144+
conf_object_t *dev, _identity_t id) {
3145+
_dml_log_object_assoc_t obj_assoc = object_assocs[id.id - 1];
3146+
if (!obj_assoc.index_divisor) return dev;
3147+
return ((conf_object_t **)((char *)dev + obj_assoc.port_obj_offset))[
3148+
id.encoded_index / obj_assoc.index_divisor];
3149+
}
3150+
31373151
static attr_value_t
31383152
_serialize_array_aux(const uint8 *data, size_t elem_size,
31393153
const uint32 *dimsizes, uint32 dims,

py/dml/c_backend.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2143,7 +2143,38 @@ def generate_object_vtables_array():
21432143
items.append(pointer)
21442144
init = '{%s}' % (', '.join(items),)
21452145
add_variable_declaration(
2146-
'void * const _object_vtables[%d]' % (len(dml.globals.objects)),
2146+
f'void * const _object_vtables[{len(dml.globals.objects)}]', init)
2147+
2148+
def generate_log_object_assocs_array():
2149+
items = []
2150+
for node in dml.globals.objects:
2151+
object_node = (node if node.objtype in {'device', 'bank',
2152+
'subdevice', 'port'}
2153+
else node.object_parent)
2154+
if (object_node is not dml.globals.device
2155+
# Anonymous banks
2156+
and not (compat.dml12_misc in dml.globals.enabled_compat
2157+
and object_node.ident is None)
2158+
# HACK compile errors may lead to .name of nodes never being set.
2159+
# This issue has proven difficult to fix due to multiple technical
2160+
# debts, most egregiously that the various uses of
2161+
# dml.globals.objects and dml.globals.hooks don't properly take
2162+
# into account the possibility of objects becoming rejected
2163+
and object_node.name is not None):
2164+
port_obj_offset = (
2165+
f'offsetof({crep.structtype(dml.globals.device)}, '
2166+
+ f'{crep.cref_portobj(object_node, ())})')
2167+
index_divisor = str(reduce(
2168+
operator.mul,
2169+
itertools.islice(node.dimsizes, object_node.dimensions, None),
2170+
1))
2171+
else:
2172+
port_obj_offset = index_divisor = '0'
2173+
items.append(f'{{{port_obj_offset}, {index_divisor}}}')
2174+
init = f'{{{", ".join(items)}}}'
2175+
add_variable_declaration(
2176+
'const _dml_log_object_assoc_t '
2177+
+ f'_log_object_assocs[{len(dml.globals.objects)}]',
21472178
init)
21482179

21492180
def generate_trait_method(m):
@@ -3297,6 +3328,7 @@ def generate_cfile_body(device, footers, full_module, filename_prefix):
32973328
generate_events(device)
32983329
generate_identity_data_decls()
32993330
generate_object_vtables_array()
3331+
generate_log_object_assocs_array()
33003332
generate_class_var_decl()
33013333
generate_startup_calls_entry_function(device)
33023334
generate_init_data_objs(device)

py/dml/codegen.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ def __init__(self, site, node, indices):
167167
self.indices = indices
168168

169169
def fail(self, site):
170-
return log_statement(site, self.node, self.indices, "error",
171-
mkIntegerLiteral(site, 1), None,
170+
return log_statement(site, log_object(site, self.node, self.indices),
171+
"error", mkIntegerLiteral(site, 1), None,
172172
"Uncaught DML exception")
173173

174174
class ReturnFailure(Failure):
@@ -2640,6 +2640,15 @@ def stmt_log(stmt, location, scope):
26402640
else:
26412641
warn_mixup = probable_loggroups_specification(level)
26422642

2643+
# Acquire a subsequent log key and the logging object based on obj or trait
2644+
# identity
2645+
if location.method():
2646+
identity = ObjIdentity(site, location.node.parent, location.indices)
2647+
logobj = log_object(site, location.node, location.indices)
2648+
else:
2649+
identity = TraitObjIdentity(site, lookup_var(site, scope, "this"))
2650+
logobj = LogObjectFromObjIdentity(site, identity)
2651+
26432652
if later_level is not None:
26442653
adjusted_later_level = later_level = ctree.as_int(codegen_expression(
26452654
later_level, location, scope))
@@ -2654,14 +2663,10 @@ def stmt_log(stmt, location, scope):
26542663
global log_index
26552664
table_ptr = TPtr(TNamed("ht_int_table_t"))
26562665
table = mkLit(site, '&(_dev->_subsequent_log_ht)', table_ptr)
2657-
# Acquire a key based on obj or trait identity
2658-
if location.method():
2659-
identity = ObjIdentity(site, location.node.parent, location.indices)
2660-
else:
2661-
identity = TraitObjIdentity(site, lookup_var(site, scope, "this"))
26622666
key = mkApply(site,
26632667
mkLit(site, "_identity_to_key",
2664-
TFunction([TNamed('_identity_t')], TInt(64, False))),
2668+
TFunction([TNamed('_identity_t')],
2669+
TInt(64, False))),
26652670
[identity])
26662671

26672672
once_lookup = mkLit(
@@ -2690,8 +2695,8 @@ def stmt_log(stmt, location, scope):
26902695
report(WLOGMIXUP(site, logkind, level, later_level, groups))
26912696
fmt, args = fix_printf(fmt, args, argsites, site)
26922697
return [mkCompound(site, pre_statements + [
2693-
log_statement(site, location.node, location.indices,
2694-
logkind, adjusted_level, groups, fmt, *args)])]
2698+
log_statement(site, logobj, logkind, adjusted_level, groups, fmt,
2699+
*args)])]
26952700
@statement_dispatcher
26962701
def stmt_try(stmt, location, scope):
26972702
[tryblock, excblock] = stmt.args

py/dml/ctree.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
'ObjIdentity',
141141
'TraitObjIdentity',
142142
'ObjTraitRef',
143+
'LogObjectFromObjIdentity',
143144
'NodeArrayRef',
144145
'SessionVariableRef',
145146
'mkNodeRef', 'NodeRef',
@@ -165,6 +166,7 @@
165166
'as_int',
166167
'sym_declaration',
167168
'lookup_var',
169+
'log_object',
168170
'log_statement',
169171

170172
'all_index_exprs',
@@ -3534,6 +3536,19 @@ def ctype(self):
35343536
def read(self):
35353537
return "(%s).id" % (self.traitref.read(),)
35363538

3539+
class LogObjectFromObjIdentity(Expression):
3540+
priority = dml.expr.Apply.priority
3541+
@auto_init
3542+
def __init__(self, site, identity):
3543+
crep.require_dev(site)
3544+
3545+
def ctype(self):
3546+
return TNamed('conf_object_t *')
3547+
3548+
def read(self):
3549+
return ('_identity_to_logobj(_log_object_assocs, &_dev->obj, '
3550+
+ f'{self.identity.read()})')
3551+
35373552
class TraitUpcast(Expression):
35383553
@auto_init
35393554
def __init__(self, site, sub, parent): pass
@@ -5033,7 +5048,11 @@ def lookup_var(site, scope, name):
50335048
else:
50345049
return sym.expr(site)
50355050

5036-
def log_statement(site, node, indices, logtype, level, groups, fmt, *args):
5051+
def log_object(site, node, indices):
5052+
return mkLit(site, crep.conf_object(site, node, indices),
5053+
TPtr(TNamed("conf_object_t")))
5054+
5055+
def log_statement(site, logobj, logtype, level, groups, fmt, *args):
50375056
if logtype in ['error', 'critical']:
50385057
lvl = []
50395058
else:
@@ -5049,8 +5068,6 @@ def log_statement(site, node, indices, logtype, level, groups, fmt, *args):
50495068
TPtr(TInt(8, True, const=True))])
50505069
fun = mkLit(site, logfunc, TFunction(inargtypes, TVoid(), varargs=True))
50515070

5052-
logobj = mkLit(site, crep.conf_object(site, node, indices),
5053-
TPtr(TNamed("conf_object_t")))
50545071
x = Apply(site, fun,
50555072
lvl +
50565073
[ logobj,

py/dml/int_register.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,9 @@ def codegen_get_name(impl, indices, inargs, outargs, site):
5757
[mkCopyData(site, regname, name),
5858
mkIf(site,
5959
mkNot(site, as_bool(name)),
60-
log_statement(site, bank, indices, "error",
61-
None, None,
62-
"There is no register with number %d",
63-
num)),
60+
log_statement(site, log_object(site, bank, indices), "error",
61+
None, None, "There is no register with number %d",
62+
num)),
6463
return_success(site)])
6564

6665
def codegen_get_number(impl, indices, inargs, outargs, site):
@@ -105,8 +104,8 @@ def codegen_get_number(impl, indices, inargs, outargs, site):
105104
[mkCopyData(site,
106105
mkIntegerConstant(site, -1, True),
107106
num),
108-
log_statement(site, bank, indices, "error",
109-
None, None,
107+
log_statement(site, log_object(site, bank, indices),
108+
"error", None, None,
110109
"There is no register with name %s",
111110
name)])),
112111
return_success(site)])
@@ -155,9 +154,8 @@ def codegen_read(impl, indices, inargs, outargs, site):
155154
regvar,
156155
reg_table]),
157156
val),
158-
log_statement(site, bank, indices, "error",
159-
None, None,
160-
"There is no register with number %d",
157+
log_statement(site, log_object(site, bank, indices), "error",
158+
None, None, "There is no register with number %d",
161159
num)),
162160
return_success(site)])
163161

@@ -203,8 +201,7 @@ def codegen_write(impl, indices, inargs, outargs, site):
203201
regvar,
204202
reg_table,
205203
val])),
206-
log_statement(site, bank, indices, "error",
207-
None, None,
208-
"There is no register with number %d",
204+
log_statement(site, log_object(site, bank, indices), "error",
205+
None, None, "There is no register with number %d",
209206
num)),
210207
return_success(site)])

test/1.2/registers/T_instrumentation.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@
3838
instrumentation_connection_order.test(obj, subscribe_b1, order_b1)
3939

4040
instrumentation_access_inquire.test(obj, subscribe_b2)
41-
instrumentation_access_set_missed.test(obj, subscribe_b1, obj.bank.b1)
41+
instrumentation_access_set_missed.test(obj, subscribe_b1)
4242
instrumentation_access_set_offset.test(obj, subscribe_b1)
4343
instrumentation_access_set_value.test(obj, subscribe_b1)
4444
instrumentation_access_suppress.test(obj, subscribe_b1)
45-
instrumentation_access_value_at_miss.test(obj, subscribe_b1, obj.bank.b1)
45+
instrumentation_access_value_at_miss.test(obj, subscribe_b1)
4646
instrumentation_bank_array.test(obj, subscribe_ba[0], subscribe_ba[1])
4747
instrumentation_callback_args.test(obj, subscribe_b1)
4848
instrumentation_callback_inquiry.test(obj, subscribe_b1)
@@ -53,7 +53,7 @@
5353
instrumentation_endianness_overlapping.test(obj.bank.be, 0x010203040A0B0C0D)
5454
instrumentation_endianness_overlapping.test(obj.bank.le, 0x0A0B0C0D01020304)
5555
instrumentation_instrument_all.test(obj, subscribe_b1)
56-
instrumentation_instrument_edge.test(obj, subscribe_b1, obj.bank.b1)
56+
instrumentation_instrument_edge.test(obj, subscribe_b1)
5757
instrumentation_overlapping_order.test(obj, subscribe_b1)
5858
instrumentation_range.test(obj, subscribe_b1)
5959
instrumentation_subscribe_multiple.test(obj, subscribe_b1, subscribe_b2)

test/1.4/lib/T_map_target_connect.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@
5353

5454
obj.x_address = 0
5555
obj.log_level = 2
56-
with stest.expect_log_mgr(obj, log_type="spec-viol"):
56+
with stest.expect_log_mgr(obj.bank.z, log_type="spec-viol"):
5757
rex = re.compile("^failed to read 8 bytes @ 0x0")
5858
with stest.expect_log_mgr(obj, log_type="info", regex=rex):
5959
_ = obj.x_value
6060

6161
rex = re.compile("^failed to write 8 bytes @ 0x0")
62-
with stest.expect_exception_mgr(simics.SimExc_Attribute):
63-
with stest.expect_log_mgr(obj, log_type="info", regex=rex):
62+
with stest.expect_log_mgr(obj, log_type="info", regex=rex):
63+
with stest.expect_exception_mgr(simics.SimExc_Attribute):
6464
obj.x_value = 42
6565

test/1.4/lib/T_unmapped_access.dml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,22 @@ bank b {
6262

6363
method init() {
6464
// Check regular register semantics
65-
/// GREP \[obj spec-viol\] .*b.r1, bitranges;.*
65+
/// GREP \[obj\.bank\.b spec-viol\] .*b.r1, bitranges;.*
6666
/// GREP .*15:0 .*written = 0b1111111111111111, previous.*= 0b0000111100001111.*
6767
b.r1.write_register(0xffffffff, 0xffffffff, NULL);
6868
// No log on second write
6969
b.r1.write_register(0xffffffff, 0xffffffff, NULL);
7070

7171
// Check split ranges
72-
/// GREP \[obj spec-viol\] .*b.r1, bitranges;.*
72+
/// GREP \[obj\.bank\.b spec-viol\] .*b.r1, bitranges;.*
7373
/// GREP .*15:8 .*written = 0b11111111, previous.*= 0b00001111.*
7474
/// GREP .*3:0 .*written = 0b1111, previous.*= 0b0000.*
7575
b.r1_2.write_register(0xffffffff, 0x0000ff0f, NULL);
7676
b.r1_2.write_register(0xf0f0f0f0, 0xffffffff, NULL);
7777
assert b.r1_2.read_register(0xfffffff00, NULL) == 0xf0f0f000;
7878

7979
// segmented by field bit range
80-
/// GREP \[obj spec-viol\] .*b.r2, bitranges;.*
80+
/// GREP \[obj\.bank\.b spec-viol\] .*b.r2, bitranges;.*
8181
/// GREP .*15:8 .*written = 0b11110000, previous.*= 0b00001111.*
8282
/// GREP .*3:0 .*written = 0b1111, previous.*= 0b0000.*
8383
b.r2.write_register(0x0f0f0f0f, 0xffffffff, NULL);

0 commit comments

Comments
 (0)