47
47
* If a subcell is used and no its ExportIds are used, it is represented by empty BitSet.
49
49
class UsageCollector {
50
51
static final BitSet EMPTY_BITSET = new BitSet();
51
static final TreeMap<Variable.AttrKey,TextDescriptor.Unit> EMPTY_ATTRIBUTES = new TreeMap<Variable.AttrKey,TextDescriptor.Unit>();
52
static final TreeMap<Variable.AttrKey, TextDescriptor.Unit> EMPTY_ATTRIBUTES = new TreeMap<Variable.AttrKey, TextDescriptor.Unit>();
53
53
private final ImmutableCell d;
54
private final HashMap<CellId, CellUsageInfoBuilder> cellIndices = new HashMap<CellId,CellUsageInfoBuilder>(16, 0.5f);
55
private final HashSet<TechId> techUsed = new HashSet<TechId> (16, 0.5f);
54
private final HashMap<CellId, CellUsageInfoBuilder> cellIndices = new HashMap<CellId, CellUsageInfoBuilder>(16, 0.5f);
55
private final HashSet<TechId> techUsed = new HashSet<TechId>(16, 0.5f);
58
58
* Collect usages in lists of nodes/arcs/exports together with Cell's variables.
65
65
for (int nodeIndex = 0; nodeIndex < nodes.size(); nodeIndex++) {
66
66
ImmutableNodeInst n = nodes.get(nodeIndex);
67
67
if (n.protoId instanceof CellId) {
68
CellUsageInfoBuilder cellCount = add((CellId)n.protoId, true);
68
CellUsageInfoBuilder cellCount = add((CellId) n.protoId, true);
69
69
if (cellCount.isIcon) {
70
for (Variable param: n.getDefinedParams())
71
cellCount.addAttribute((Variable.AttrKey)param.getKey(), param.getUnit());
70
for (Variable param : n.getDefinedParams()) {
71
cellCount.addAttribute((Variable.AttrKey) param.getKey(), param.getUnit());
72
73
for (int varIndex = 0; varIndex < n.getNumVariables(); varIndex++) {
73
74
Variable.Key varKey = n.getVar(varIndex).getKey();
74
if (varKey.isAttribute())
75
cellCount.addAttribute((Variable.AttrKey)varKey, null);
75
if (varKey.isAttribute()) {
76
cellCount.addAttribute((Variable.AttrKey) varKey, null);
79
techUsed.add(((PrimitiveNodeId)n.protoId).techId);
81
techUsed.add(((PrimitiveNodeId) n.protoId).techId);
81
83
for (int chronIndex = 0; chronIndex < n.ports.length; chronIndex++) {
82
84
ImmutablePortInst pi = n.ports[chronIndex];
83
if (pi == ImmutablePortInst.EMPTY) continue;
85
if (pi == ImmutablePortInst.EMPTY) {
84
88
PortProtoId pp = n.protoId.getPortId(chronIndex);
100
104
private void add(PortProtoId portId) {
101
if (portId instanceof PrimitivePortId) return;
102
ExportId eId = (ExportId)portId;
105
if (portId instanceof PrimitivePortId) {
108
ExportId eId = (ExportId) portId;
103
109
add(eId.getParentId(), false).usedExports.set(eId.chronIndex);
120
127
BitSet getTechUsages(BitSet oldTechUsages) {
121
128
BitSet techUsages = new BitSet();
122
129
techUsages.set(d.techId.techIndex);
123
for (TechId techId: techUsed)
130
for (TechId techId : techUsed) {
124
131
techUsages.set(techId.techIndex);
125
133
return bitSetWith(oldTechUsages, techUsages);
129
137
* Return usages for CellRevision.
131
139
CellRevision.CellUsageInfo[] getCellUsages(CellRevision.CellUsageInfo[] oldCellUsages) {
132
if (cellIndices.isEmpty()) return CellRevision.NULL_CELL_USAGE_INFO_ARRAY;
140
if (cellIndices.isEmpty()) {
141
return CellRevision.NULL_CELL_USAGE_INFO_ARRAY;
133
143
CellId parentId = d.cellId;
135
for (CellId cellId: cellIndices.keySet())
145
for (CellId cellId : cellIndices.keySet()) {
136
146
length = Math.max(length, parentId.getUsageIn(cellId).indexInParent + 1);
137
148
CellRevision.CellUsageInfo[] newCellUsages = new CellRevision.CellUsageInfo[length];
138
for (CellId cellId: cellIndices.keySet()) {
149
for (CellId cellId : cellIndices.keySet()) {
139
150
CellUsage u = parentId.getUsageIn(cellId);
140
151
int indexInParent = u.indexInParent;
141
152
CellUsageInfoBuilder cellCount = cellIndices.get(cellId);
150
161
static BitSet bitSetWith(BitSet oldBitSet, BitSet newBitSet) {
151
if (newBitSet.isEmpty())
162
if (newBitSet.isEmpty()) {
152
163
return EMPTY_BITSET;
153
165
return newBitSet.equals(oldBitSet) ? oldBitSet : newBitSet;
156
static TreeMap<Variable.AttrKey,TextDescriptor.Unit> usedAttributesWith(TreeMap<Variable.AttrKey,TextDescriptor.Unit> oldAttributes,
157
TreeMap<Variable.AttrKey,TextDescriptor.Unit> newAttributes) {
158
if (newAttributes == null)
168
static TreeMap<Variable.AttrKey, TextDescriptor.Unit> usedAttributesWith(TreeMap<Variable.AttrKey, TextDescriptor.Unit> oldAttributes,
169
TreeMap<Variable.AttrKey, TextDescriptor.Unit> newAttributes) {
170
if (newAttributes == null) {
160
if (newAttributes.isEmpty())
173
if (newAttributes.isEmpty()) {
161
174
return EMPTY_ATTRIBUTES;
162
176
return newAttributes.equals(oldAttributes) ? oldAttributes : newAttributes;
165
179
private static class CellUsageInfoBuilder {
166
181
private final CellUsage cellUsage;
167
182
private final boolean isIcon;
168
183
private int instCount;
178
193
private void addAttribute(Variable.AttrKey attrKey, TextDescriptor.Unit unit) {
179
194
TextDescriptor.Unit oldUnit = usedAttributes.get(attrKey);
180
195
if (oldUnit != null) {
196
if (unit != oldUnit) {
182
197
throw new IllegalArgumentException(attrKey + " " + unit);
184
200
usedAttributes.put(attrKey, unit);
188
204
private CellRevision.CellUsageInfo getCellUsageInfo(CellRevision.CellUsageInfo oldCellUsageInfo) {
189
if (oldCellUsageInfo != null)
205
if (oldCellUsageInfo != null) {
190
206
return oldCellUsageInfo.with(instCount, usedExports, usedAttributes);
192
208
return new CellRevision.CellUsageInfo(instCount, usedExports, usedAttributes);