-
Notifications
You must be signed in to change notification settings - Fork 48
/
Copy pathudi_backend.py
170 lines (153 loc) · 5.46 KB
/
udi_backend.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# © 2021-2022 Intel Corporation
# SPDX-License-Identifier: MPL-2.0
# Generates Unrolled Device Info
__all__ = ('generate',)
import itertools
import json
from . import ctree, crep, expr_util, types
from . import logging
from .expr import mkLit
from .logging import dollar
from .codegen import eval_initializer
from .symtab import global_scope
import dml.globals
def array_info(obj):
return list(zip(obj._arraylens, obj._idxvars))
def enc(expr):
if expr.constant:
val = expr.value
if isinstance(val, list):
return [enc(e) for e in val]
elif isinstance(val, bytes):
return val.decode("utf-8")
else:
return val
else:
return str(expr)
def en_parameter(node, indices = []):
try:
expr = node.get_expr(tuple(indices))
except logging.DMLError:
import os, sys, traceback
if os.getenv('DMLC_DEBUG'):
sys.stderr.write("error encoding parameter: %s" % node)
traceback.print_exc()
return None
else:
return {node.name : enc(expr)}
def evaluate_init_value(node, indices):
if node.astinit:
return enc(eval_initializer(
node.site, node._type, node.astinit,
ctree.Location(node.parent, tuple(indices)),
global_scope, True).as_expr(node._type))
else:
return None
def en_data(node, indices = []):
return {node.name : { "init_value" : evaluate_init_value(node, indices) }}
def en_var(node, indices = []):
return {node.name : { "type" : str(node._type),
"init_value" : evaluate_init_value(node, indices) }}
def en_compobj(node, indices = []):
def do_enc(node, proper_indices):
content = {}
for trait in node.traits.ancestors:
content.setdefault("templates", []).append(trait.name)
en_subobjs(content, node, proper_indices)
return content
new_indices = [[ctree.mkIntegerConstant(node.site, i, False)
for i in range(arrsize)] for arrsize in node._arraylens]
if new_indices:
new_indices = itertools.product(*new_indices)
expanded = {}
for extra_indices in new_indices:
full_name = "{}{}".format(node.name,
"".join("[{}]".format(enc(ind)) for
ind in extra_indices))
expanded[full_name] = do_enc(node, indices + list(extra_indices))
return expanded
else:
content = {}
en_subobjs(content, node, indices)
return {node.name : do_enc(node, indices)}
obj_encoder_map = {
'attribute' : ("attributes", en_compobj),
'bank' : ("banks", en_compobj),
'connect' : ("connects", en_compobj),
'data' : ("data", en_data),
'field' : ("fields", en_compobj),
'group' : ("groups", en_compobj),
'implement' : ("implements", en_compobj),
'parameter' : ("parameters", en_parameter),
'register' : ("registers", en_compobj),
'session' : ("data", en_var),
'saved' : ("data", en_var)
}
def en_obj(output, obj, indices = []):
if obj.objtype in obj_encoder_map:
(collection, encoder) = obj_encoder_map[obj.objtype]
subobjdict = encoder(obj, indices)
output.setdefault(collection, {}).update(subobjdict)
def subobjs(node):
for s in node.get_components():
# skip implicit field
if s.objtype == 'field' and not s.name:
continue
# skip "internal" objects
if s.name.startswith("_"):
continue
# skip auto and non-interested parameters
if s.objtype == 'parameter':
if s.name in ('this', 'name', 'qname', 'parent', 'index',
'indexvar', 'shown_desc', 'objtype',
'dev', 'bank',
'documentation', 'shown_documentation',
'limitations', 'shown_limitations',
'dml_1_4', "dml_1_2"):
continue
if (node.objtype == 'device' and
s.name in ('obj', 'logobj', 'simics_api_version',
'banks', 'simics_bool_is_int')):
continue
if (node.objtype == 'bank' and
s.name in ('mapped_registers', 'unmapped_registers',
'numbered_registers')):
continue
if (node.objtype == 'register' and
s.name in ('notinregister', 'fields', '_regname')):
continue
if (node.objtype == 'field' and
s.name in ('notinfield', 'reg',)):
continue
yield s
def en_subobjs(output, obj, indices = []):
for s in subobjs(obj):
en_obj(output, s, indices)
# layout:
# {classname:
# DML: <version>,
# banks: {
# <bank>: {
# stuff,
# registers: {
# <register>: {
# stuff,
# fields: {
# <field> : {stuff}
# },
# },
# },
# },
# }
# }
def generate(classname, device, dml_version, out_file):
# Setting things up like this, allows easy combination and sorting of
# devices in later tools
complete_json = {
classname : {
"DML" : dml_version,
}
}
complete_json[classname].update(en_compobj(device)[device.name])
with open(out_file, "w") as outfile:
json.dump(complete_json, outfile)