Ejemplo n.º 1
0
 def connect_to(self, other: PinIn):
     if self._assignment is None:
         alias_wire = self.parent.create_wire()
         if self._source is not None:
             source = self._source
             source.unbind()
             source.bind(alias_wire)
         self._assignment = self.parent.add_alias(alias_wire.name, self.name)
     other.bind(self.alias)
 def __init__(self, parent: Module, source: Wire, delay: int):
     super().__init__("{}_v_buffer".format(source.name), parent)
     buf_out = parent.create_wire()
     org_post = set(source.post)
     for p in org_post:
         p.unbind()
         p.bind(buf_out)
     self._input = PinIn("v_bfr_in", self, source)
     self._output = PinOut("v_bfr_out", self, buf_out)
     self._delay = delay
 def __init__(self,
              parent: Module,
              source: Wire,
              child_wires: Dict[Wire, int] = None):
     super().__init__("{}_v_fanout".format(source.name), parent)
     self._before = 0
     self._tracker = 0
     self._outputs = set()
     self._after = dict()
     if child_wires is None:
         org_post = set(source.post)
         for p in org_post:
             p.unbind()
             split_out_wire = parent.create_wire()
             p.bind(split_out_wire)
             self._add_wire(split_out_wire)
     else:
         for p in child_wires.keys():
             self._add_wire(p, child_wires[p])
     self._input = PinIn("v_fanout_in", self, source)
Ejemplo n.º 4
0
class Alias(UnitBlock):
    def __init__(self, name: str, parent: (Block, Device), org: Net,
                 alias: Net):
        super().__init__(name, parent)
        self._input = PinIn("alias", self, alias)
        self._output = PinOut("org", self, org)

    def unbind(self):
        self._input.unbind()
        self._output.unbind()

    @property
    def wire_in(self):
        return self._input.connection

    @property
    def wire_out(self):
        return self._output.connection

    @property
    def input_pins(self):
        return [self._input]

    @property
    def output_pins(self):
        return [self._output]

    @property
    def gate_count(self):
        return 0

    def get_delay(self, other=None):
        return 0

    def truth_table(self, other):
        return 1

    def to_verilog(self):
        return "\tassign {} = {};".format(self._output.connection.name,
                                          self._input.connection.name)
Ejemplo n.º 5
0
 def __init__(self, name: str, parent: Device, model: Device,
              mapping: Dict[str, Net]):
     super().__init__(name, parent)
     self._model = model
     self._pins = dict()
     self._inputs = list()
     self._outputs = list()
     for x in model.input_labels:
         pin = PinIn(x, self, mapping.get(x))
         self._pins[x] = pin
         self._inputs.append(pin)
     for x in model.output_labels:
         pin = PinOut(x, self, mapping.get(x))
         self._pins[x] = pin
         self._outputs.append(pin)
class Distributor(LogicBlock):
    def __init__(self,
                 parent: Module,
                 source: Wire,
                 child_wires: Dict[Wire, int] = None):
        super().__init__("{}_v_fanout".format(source.name), parent)
        self._before = 0
        self._tracker = 0
        self._outputs = set()
        self._after = dict()
        if child_wires is None:
            org_post = set(source.post)
            for p in org_post:
                p.unbind()
                split_out_wire = parent.create_wire()
                p.bind(split_out_wire)
                self._add_wire(split_out_wire)
        else:
            for p in child_wires.keys():
                self._add_wire(p, child_wires[p])
        self._input = PinIn("v_fanout_in", self, source)

    def _add_wire(self, other: Wire, delay: int = 0):
        split_out_pin = PinOut("v_fanout_out_{}".format(str(self._tracker)),
                               self, other)
        self._outputs.add(split_out_pin)
        self._tracker = self._tracker + 1
        self._after[split_out_pin.name] = delay

    def _create_parent_splitter(self):
        old_source = self._input.connection
        new_source = self.parent.create_wire()
        self._input.unbind()
        self._input.bind(new_source)
        self.name = "{}_v_fanout".format(new_source.name)
        upper = Distributor(self.parent, old_source)
        upper._add_wire(new_source)
        if self._before > 0:
            self._before = self._before - 1
        return upper

    def _pop_out(self, pin: PinOut = None):
        if pin is None:
            pin = self._outputs.pop()
        else:
            self._outputs.remove(pin)
        delay = self._after[pin.name]
        wire = pin.connection
        pin.unbind()
        del self._after[pin.name]
        return wire, delay

    def _decompose(self, degree: int):
        total = len(self._outputs)
        basket = list()
        for i in range(int(total / degree)):
            basket.append(degree)
        if total % degree == 1:
            basket[-1] = basket[-1] - 1
        elif total % degree == 0:
            del basket[-1]
        return basket

    def add_delay(self, other: str, margin: int):
        if self._after.get(other) is None:
            print("No such connection")
            return
        self._after[other] = self._after.get(other) + margin

    def buffer_float(self):
        mutual = min(self._after.values())
        if mutual != 0:
            self._before = self._before + mutual
            for k in self._after.keys():
                self._after[k] = self._after[k] - mutual
        if isinstance(self._input.connection.source_instance, Distributor):
            self._input.connection.source_instance.add_delay(
                self._input.connection.source.name, self._before)
            self._before = 0

    def splitter_submerge(self, results: list):
        threashold = min(self._after.values())
        to_next = {
            x
            for x in self._outputs if self._after.get(x.name) > threashold
        }
        if len(to_next) <= 1:
            results.append(self)
            return
        internal_splitter = self.parent.create_wire()
        self._add_wire(internal_splitter)
        to_next_wires = dict()
        for x in to_next:
            wire, delay = self._pop_out(x)
            to_next_wires[wire] = delay - 1
        child_splitter = Distributor(self.parent, internal_splitter,
                                     to_next_wires)
        child_splitter.splitter_submerge(results)
        results.append(self)

    def break_up(self, degree: int, extra_splitters: set,
                 dependency_list: list):
        if len(self._outputs) <= degree:
            self.buffer_float()
            return
        upper = self._input.connection.source_instance
        if not isinstance(upper, Distributor):
            upper = self._create_parent_splitter()
        extra_splitters.add(upper)
        self.buffer_float()
        basket = self._decompose(degree)
        for item in basket:
            internal_wires = dict()
            for i in range(item):
                wire, delay = self._pop_out()
                internal_wires[wire] = delay
            sibling = self.parent.create_wire()
            extra_splitters.add(
                Distributor(self.parent, sibling, internal_wires))
            upper._add_wire(sibling)
        if upper not in dependency_list:
            upper.break_up(degree, extra_splitters, dependency_list)

    @property
    def source(self):
        return self._input.connection

    @property
    def input_pins(self):
        return [self._input]

    @property
    def fan_out(self):
        return len(self.output_pins)

    @property
    def output_pins(self):
        return self._outputs

    def get_delay(self, other: str):
        if self._after.get(other) is None:
            print("No such connection")
            return
        return self._before + 1 + self._after.get(other)

    @property
    def max_delay(self):
        return self._before + 1 + max(self._after.values())

    @property
    def gate_count(self):
        return 2 + self._before * 2 + 2 * sum(x for x in self._after.values())

    def to_verilog(self):
        return "Black box"

    def cell_mapping(self, library: Library):
        buffer_model = library.get_buffer()
        input_wire = self._input.connection
        self._input.unbind()
        for i in range(self._before):
            wire_down = self.parent.create_wire()
            self.parent.register_instance(
                buffer_model.instantiate("{}_bfr_after".format(wire_down.name),
                                         self.parent, [input_wire, wire_down]))
            input_wire = wire_down
        wires = [input_wire]
        for x in self._outputs:
            output_wire = x.connection
            delay = self._after[x.name]
            x.unbind()
            for i in range(delay):
                wire_up = self.parent.create_wire()
                self.parent.register_instance(
                    buffer_model.instantiate(
                        "{}_bfr_before".format(wire_up.name), self.parent,
                        [wire_up, output_wire]))
                output_wire = wire_up
            wires.append(output_wire)
        splitter_model = library.get_splitter(self.fan_out)
        self.parent.register_instance(
            splitter_model.instantiate(self.name, self.parent, wires))
class VirtualBuffer(LogicBlock):
    def __init__(self, parent: Module, source: Wire, delay: int):
        super().__init__("{}_v_buffer".format(source.name), parent)
        buf_out = parent.create_wire()
        org_post = set(source.post)
        for p in org_post:
            p.unbind()
            p.bind(buf_out)
        self._input = PinIn("v_bfr_in", self, source)
        self._output = PinOut("v_bfr_out", self, buf_out)
        self._delay = delay

    @property
    def input_pins(self):
        return [self._input]

    @property
    def output_pins(self):
        return {self._output}

    def get_delay(self, other=None):
        return self._delay

    def decrease(self, margin: int = 1):
        if self._delay == 0:
            print("delay is already 0")
            return
        self._delay = self._delay - margin
        if self._delay == 0:
            source = self._input.connection
            self._input.unbind()
            to = self._output.connection
            self._output.unbind()
            to.post.pop().bind(source)
            self.parent.remove_net(to.name)

    def increase(self, margin: int = 1):
        self._delay = self._delay + margin

    @property
    def gate_count(self):
        return 2 * self._delay

    def to_verilog(self):
        return "Black box"

    def cell_mapping(self, library):
        if self._delay == 0:
            return
        buffer_model = library.get_buffer()
        input_wire = self._input.connection
        self._input.unbind()
        for i in range(self._delay - 1):
            wire_down = self.parent.create_wire()
            self.parent.register_instance(
                buffer_model.instantiate("{}_bfr_after".format(wire_down.name),
                                         self.parent, [input_wire, wire_down]))
            input_wire = wire_down
        output_wire = self._output.connection
        self._output.unbind()
        self.parent.register_instance(
            buffer_model.instantiate("{}_bfr_after".format(output_wire.name),
                                     self.parent, [input_wire, output_wire]))
Ejemplo n.º 8
0
 def __init__(self, name: str, parent: (Block, Device), org: Net,
              alias: Net):
     super().__init__(name, parent)
     self._input = PinIn("alias", self, alias)
     self._output = PinOut("org", self, org)
class Distributor(LogicBlock):
    def __init__(self,
                 parent: Module,
                 source: Wire,
                 child_wires: Dict[Wire, int] = None):
        super().__init__("{}_v_fanout".format(source.name), parent)
        self._before = 0
        self._tracker = 0
        self._outputs = set()
        self._after = dict()
        self._delay_est = 1
        self._gate = 1
        if child_wires is None:
            org_post = set(source.post)
            for p in org_post:
                p.unbind()
                split_out_wire = parent.create_wire()
                p.bind(split_out_wire)
                self._add_wire(split_out_wire)
        else:
            for p in child_wires.keys():
                self._add_wire(p, child_wires[p])
        self._input = PinIn("v_fanout_in", self, source)

    def __hash__(self):
        return hash(self.name)

    def ideal_case(self):
        self._delay_est = 1
        self._gate = 1

    def reset_delay(self):
        self._before = 0
        for a in self._after.keys():
            self._after[a] = 0

    def worst_case(self, limit=2):
        self._delay_est = math.ceil(math.log(len(self._outputs), limit))
        self._gate = sum(limit**i for i in range(self._delay_est))

    def _add_wire(self, other: Wire, delay: int = 0):
        split_out_pin = PinOut("v_fanout_out_{}".format(str(self._tracker)),
                               self, other)
        self._outputs.add(split_out_pin)
        self._tracker = self._tracker + 1
        self._after[split_out_pin.name] = delay

    def _level_up(self):
        new_source = self.parent.create_wire()
        internal_wires = dict()
        fo = len(self._outputs)
        for i in range(fo):
            wire, delay = self._pop_out()
            if delay > 0:
                delay = delay - 1
            internal_wires[wire] = delay
        ds = Distributor(self.parent, new_source, internal_wires)
        self._add_wire(new_source)
        return ds

    def _pop_out(self, pin: PinOut = None):
        if pin is None:
            pin = self._outputs.pop()
        else:
            self._outputs.remove(pin)
        delay = self._after[pin.name]
        wire = pin.connection
        pin.unbind()
        del self._after[pin.name]
        return wire, delay

    def _decompose(self, degree: int):
        total = len(self._outputs)
        basket = list()
        while total > degree:
            basket.append(degree)
            total = total - degree
        if total != 0:
            basket.append(total)
        if len(basket) > 1:
            if basket[-1] == 1:
                basket[-2] = basket[-2] - 1
        del basket[-1]
        return basket

    def add_delay(self, other: str, margin: int):
        if self._after.get(other) is None:
            print("No such connection")
            return
        self._after[other] = self._after.get(other) + margin

    def buffer_float(self):
        mutual = min(self._after.values())
        if mutual != 0:
            self._before = self._before + mutual
            for k in self._after.keys():
                self._after[k] = self._after[k] - mutual
        if isinstance(self._input.connection.source_instance, Distributor):
            self._input.connection.source_instance.add_delay(
                self._input.connection.source.name, self._before)
            self._before = 0

    def splitter_submerge(self):
        threashold = min(self._after.values())
        to_next = {
            x
            for x in self._outputs if self._after.get(x.name) > threashold
        }
        if len(to_next) <= 1:
            return self
        internal_splitter = self.parent.create_wire()
        self._add_wire(internal_splitter)
        to_next_wires = dict()
        for x in to_next:
            wire, delay = self._pop_out(x)
            to_next_wires[wire] = delay - 1
        child_splitter = Distributor(self.parent, internal_splitter,
                                     to_next_wires)
        return child_splitter.splitter_submerge()

    def break_up(self, degree: int, extra_splitters: set):
        if self in extra_splitters:
            print(self.name, self.fan_out)
        if len(self._outputs) <= degree:
            extra_splitters.add(self)
            self.buffer_float()
            upper = self._input.connection.source_instance
            if not isinstance(upper, Distributor):
                return
            else:
                return upper.break_up(degree, extra_splitters)
        upper = self._input.connection.source_instance
        if not isinstance(upper, Distributor):
            lower = self._level_up()
            return lower.break_up(degree, extra_splitters)
        extra_splitters.add(self)
        basket = self._decompose(degree)
        for item in basket:
            internal_wires = dict()
            for i in range(item):
                wire, delay = self._pop_out()
                internal_wires[wire] = delay
            sibling = self.parent.create_wire()
            ds = Distributor(self.parent, sibling, internal_wires)
            extra_splitters.add(ds)
            upper._add_wire(sibling)
            ds.buffer_float()
        self.buffer_float()
        return upper.break_up(degree, extra_splitters)

    @property
    def source(self):
        return self._input.connection

    @property
    def input_pins(self):
        return [self._input]

    @property
    def fan_out(self):
        return len(self._outputs)

    @property
    def output_pins(self):
        return self._outputs

    def get_delay(self, other: str):
        if self._after.get(other) is None:
            print("No such connection")
            return
        return self._before + self._delay_est + self._after.get(other)

    @property
    def max_delay(self):
        return self._before + self._delay_est + max(self._after.values())

    @property
    def ideal_gate_count(self):
        dls = list(self._after.values())
        finals = list()
        level = 1
        while (True):
            count = sum(x > min(dls) for x in dls)
            if count <= 1:
                finals = dls
                break
            level = level + 1
            finals.extend([x for x in dls if x == min(dls)])
            dls = [x - 1 for x in dls if x > min(dls)]
            level = level + min(dls)
            dls = [x - min(dls) for x in dls]
        return 2 * level + self._before * 2 + 2 * sum(finals)

    @property
    def gate_count(self):
        return 2 * self._gate + self._before * 2 + 2 * sum(
            x for x in self._after.values())

    def to_verilog(self):
        return "Black box"

    def cell_mapping(self, library: Library):
        buffer_model = library.get_buffer()
        input_wire = self._input.connection
        self._input.unbind()
        for i in range(self._before):
            wire_down = self.parent.create_wire()
            self.parent.register_instance(
                buffer_model.instantiate("{}_bfr_after".format(wire_down.name),
                                         self.parent, [input_wire, wire_down]))
            input_wire = wire_down
        wires = [input_wire]
        for x in self._outputs:
            output_wire = x.connection
            delay = self._after[x.name]
            x.unbind()
            for i in range(delay):
                wire_up = self.parent.create_wire()
                self.parent.register_instance(
                    buffer_model.instantiate(
                        "{}_bfr_before".format(wire_up.name), self.parent,
                        [wire_up, output_wire]))
                output_wire = wire_up
            wires.append(output_wire)
        splitter_model = library.get_splitter(self.fan_out)
        self.parent.register_instance(
            splitter_model.instantiate(self.name, self.parent, wires))