Skip to content

Commit

Permalink
LVS: make compilation reproducible
Browse files Browse the repository at this point in the history
  • Loading branch information
zjkmxy committed Oct 24, 2024
1 parent 80aeeec commit 02e70bc
Showing 1 changed file with 21 additions and 8 deletions.
29 changes: 21 additions & 8 deletions src/ndn/app_support/light_versec/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ def top_order(nodes: set[T], graph: dict[T, list[T]]) -> list[T]:
if not cur_round:
remaining_nodes = nodes - set(ret)
raise SemanticError(f'Loop detected for {remaining_nodes}')
# Sort for stable build. Allowed since T can only be `str` or `int`
cur_round.sort()
for n in cur_round:
for n2 in graph[n]:
in_degs[n2] -= 1
Expand Down Expand Up @@ -219,7 +221,7 @@ def _gen_pattern_numbers(self):
def _replicate_rules(self):
self.rep_rules = {}
for rule in self.lvs.rules:
sign_cons = [s.id for s in rule.sign_cons]
sign_cons = sorted([s.id for s in rule.sign_cons])
if not rule.comp_cons:
cur_chains = [self.RuleChain(id=rule.id.id, name=[], cons_set=[], sign_cons=sign_cons)]
else:
Expand All @@ -230,6 +232,7 @@ def _replicate_rules(self):
for chain in cur_chains:
chain.name.append(comp)
else:
# Note: this repeats temporary tag numbers, which needs to be fixed before emit.
new_chains = [self.RuleChain(id=rule.id.id,
name=chain.name+ref_chain.name,
cons_set=chain.cons_set+ref_chain.cons_set,
Expand All @@ -253,7 +256,8 @@ def _generate_node(self, depth: int, context: list[RuleChain], parent: Optional[
for rc in context:
if depth == len(rc.name):
node.rule_name.append(rc.id)
# Here we violate the type. Will fix it later
# Here we violate the type (expected list[int], actual list[str]).
# Will fix it later in `_fix_signing_references`
node.sign_cons.extend(rc.sign_cons)
if rc.id not in self.rule_node_ids:
self.rule_node_ids[rc.id] = [node.id]
Expand All @@ -266,7 +270,8 @@ def _generate_node(self, depth: int, context: list[RuleChain], parent: Optional[
v_move = set(rc.name[depth].c for rc in context
if isinstance(rc.name[depth], psr.ComponentValue))
node.v_edges = []
for v in v_move:
v_move_list = sorted(list(v_move))
for v in v_move_list:
new_context = [rc for rc in context
if isinstance(rc.name[depth], psr.ComponentValue)
and rc.name[depth].c == v]
Expand All @@ -277,7 +282,7 @@ def _generate_node(self, depth: int, context: list[RuleChain], parent: Optional[
# Pattern movements
p_moves = [rc.pattern_movement(depth, previous_tags) + (rc,) for rc in context
if isinstance(rc.name[depth], psr.Pattern)]
p_move_strs = set(pm[2] for pm in p_moves)
p_move_strs = sorted(list(set(pm[2] for pm in p_moves)))
for pm_str in p_move_strs:
new_context = [pm[3] for pm in p_moves if pm[2] == pm_str]
assert len(new_context) > 0
Expand All @@ -294,6 +299,9 @@ def _generate_node(self, depth: int, context: list[RuleChain], parent: Optional[
return node.id

def _fix_signing_references(self):
"""
Convert signing constraints from string node-ID to integer node-ID
"""
for node in self.node_pool:
sign_cons = node.sign_cons
if not sign_cons:
Expand All @@ -303,28 +311,33 @@ def _fix_signing_references(self):
if rid not in self.rule_node_ids:
raise SemanticError(f'Signed by a non-existing key {rid}')
new_sign_cons.extend(self.rule_node_ids[rid])
node.sign_cons = new_sign_cons
node.sign_cons = sorted(new_sign_cons)

def compile(self) -> bny.LvsModel:
self._sort_rule_references()
self._gen_pattern_numbers()
self._replicate_rules()
self.node_pool = []
self.rule_node_ids = {}
rule_chains = sum(self.rep_rules.values(), [])
# Sort replicated rules for compilation stability
sorted_rep_rules = list(self.rep_rules.items())
sorted_rep_rules.sort(key=lambda tup: tup[0])
rule_chains = sum([v for (k, v) in sorted_rep_rules], start=[])
start_node = self._generate_node(0, rule_chains, None, set())
self._fix_signing_references()
ret = bny.LvsModel()
ret.version = bny.VERSION
ret.start_id = start_node
ret.named_pattern_cnt = len(self.named_pats)
ret.nodes = self.node_pool
ret.symbols = []
symbols = []
for pname, number in self.named_pats.items():
symbol = bny.TagSymbol()
symbol.ident = pname
symbol.tag = int(number)
ret.symbols.append(symbol)
symbols.append(symbol)
symbols.sort(key=lambda sym: sym.tag)
ret.symbols = symbols
return ret


Expand Down

0 comments on commit 02e70bc

Please sign in to comment.