Sometimes round down pdriver to fix polarity

This commit is contained in:
Matthew Guthaus 2019-11-06 21:51:21 +00:00
parent 35e65fc6f2
commit a2422cc8d4
2 changed files with 44 additions and 21 deletions

View File

@ -27,12 +27,12 @@ class pdriver(pgate.pgate):
self.size_list = size_list self.size_list = size_list
self.fanout = fanout self.fanout = fanout
if not size_list and self.fanout == 0: debug.check(self.size_list or self.fanout > 0,
debug.error("Either fanout or size list must be specified.", -1) "Either fanout or size list must be specified.")
if self.size_list and self.fanout != 0: debug.check(not (self.size_list and self.fanout > 0),
debug.error("Cannot specify both size_list and fanout.", -1) "Cannot specify both size_list and fanout.")
if self.size_list and self.neg_polarity: debug.check(not (self.size_list and self.neg_polarity),
debug.error("Cannot specify both size_list and neg_polarity.", -1) "Cannot specify both size_list and neg_polarity.")
# Creates the netlist and layout # Creates the netlist and layout
pgate.pgate.__init__(self, name, height) pgate.pgate.__init__(self, name, height)
@ -43,21 +43,44 @@ class pdriver(pgate.pgate):
self.num_stages = len(self.size_list) self.num_stages = len(self.size_list)
else: else:
# Find the optimal number of stages for the given effort # Find the optimal number of stages for the given effort
self.num_stages = max(1, optimal_stages = self.fanout ** (1 / self.stage_effort)
int(round(self.fanout ** (1 / self.stage_effort)))) rounded_stages = int(round(optimal_stages))
difference = optimal_stages - rounded_stages
# Increase the number of stages if we need to fix polarity
if self.neg_polarity and (self.num_stages % 2 == 0): # Determine if we need to fix the polarity
self.num_stages += 1 if self.neg_polarity and (rounded_stages % 2 == 0):
elif not self.neg_polarity and (self.num_stages % 2): wrong_polarity = True
self.num_stages += 1 elif not self.neg_polarity and (optimal_stages % 2):
wrong_polarity = True
else:
wrong_polarity = False
# Depending on the difference, round up or down.
if wrong_polarity:
# If we rounded up and can round down, do it.
if difference < 0 and rounded_stages > 1:
rounded_stages -= 1
else:
# Otherwise, we must round up
rounded_stages += 1
if self.neg_polarity:
# Need at least one stage for negative
self.num_stages = max(1, rounded_stages)
else:
# Need at least two stages for positive
self.num_stages = max(2, rounded_stages)
# Use the actual stage effort
actual_stage_effort = self.fanout / self.num_stages
self.size_list = [] self.size_list = []
# compute sizes backwards from the fanout # compute sizes backwards from the fanout
fanout_prev = self.fanout fanout_prev = self.fanout
for x in range(self.num_stages): for x in range(self.num_stages):
fanout_prev = max(round(fanout_prev / self.stage_effort), 1) fanout_prev = fanout_prev / actual_stage_effort
self.size_list.append(fanout_prev) self.size_list.append(max(round(fanout_prev), 1))
# reverse the sizes to be from input to output # reverse the sizes to be from input to output
self.size_list.reverse() self.size_list.reverse()