From: Sebastien Bourdeauducq Date: Fri, 22 Feb 2013 22:19:37 +0000 (+0100) Subject: corelogic -> genlib X-Git-Tag: 24jan2021_ls180~2099^2~691 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f9acee4e68471c0084cb1247f688d0d02edfb982;p=litex.git corelogic -> genlib --- diff --git a/examples/basic/complex.py b/examples/basic/complex.py index d0e61e5e..8404cec5 100644 --- a/examples/basic/complex.py +++ b/examples/basic/complex.py @@ -1,4 +1,4 @@ -from migen.corelogic.complex import * +from migen.genlib.complex import * from migen.fhdl import verilog w = Complex(32, 42) diff --git a/examples/basic/fsm.py b/examples/basic/fsm.py index f1716aea..4eedd97e 100644 --- a/examples/basic/fsm.py +++ b/examples/basic/fsm.py @@ -1,6 +1,6 @@ from migen.fhdl.structure import * from migen.fhdl import verilog -from migen.corelogic.fsm import FSM +from migen.genlib.fsm import FSM s = Signal() myfsm = FSM("FOO", "BAR") diff --git a/examples/basic/namer.py b/examples/basic/namer.py index 2928c840..80f86b54 100644 --- a/examples/basic/namer.py +++ b/examples/basic/namer.py @@ -1,6 +1,6 @@ from migen.fhdl.structure import * from migen.fhdl import verilog -from migen.corelogic.misc import optree +from migen.genlib.misc import optree def gen_list(n): s = [Signal() for i in range(n)] diff --git a/examples/basic/two_dividers.py b/examples/basic/two_dividers.py index d82f8af1..1d15aea2 100644 --- a/examples/basic/two_dividers.py +++ b/examples/basic/two_dividers.py @@ -1,5 +1,5 @@ from migen.fhdl import verilog -from migen.corelogic import divider +from migen.genlib import divider d1 = divider.Divider(16) d2 = divider.Divider(16) diff --git a/examples/basic/using_record.py b/examples/basic/using_record.py index 8e715a51..15988e83 100644 --- a/examples/basic/using_record.py +++ b/examples/basic/using_record.py @@ -1,5 +1,5 @@ from migen.fhdl.structure import * -from migen.corelogic.record import * +from migen.genlib.record import * L = [ ("x", 10, 8), diff --git a/examples/sim/fir.py b/examples/sim/fir.py index a2369503..e113154a 100644 --- a/examples/sim/fir.py +++ b/examples/sim/fir.py @@ -7,7 +7,7 @@ import matplotlib.pyplot as plt from migen.fhdl.structure import * from migen.fhdl import verilog -from migen.corelogic.misc import optree +from migen.genlib.misc import optree from migen.fhdl import autofragment from migen.sim.generic import Simulator, PureSimulable diff --git a/migen/actorlib/dma_asmi.py b/migen/actorlib/dma_asmi.py index 1f6d5d0b..65d05ca8 100644 --- a/migen/actorlib/dma_asmi.py +++ b/migen/actorlib/dma_asmi.py @@ -1,6 +1,6 @@ from migen.fhdl.structure import * from migen.flow.actor import * -from migen.corelogic.buffers import ReorderBuffer +from migen.genlib.buffers import ReorderBuffer class SequentialReader(Actor): def __init__(self, port): diff --git a/migen/actorlib/misc.py b/migen/actorlib/misc.py index 0115f56f..b0799706 100644 --- a/migen/actorlib/misc.py +++ b/migen/actorlib/misc.py @@ -1,6 +1,6 @@ from migen.fhdl.structure import * -from migen.corelogic.record import * -from migen.corelogic.fsm import * +from migen.genlib.record import * +from migen.genlib.fsm import * from migen.flow.actor import * # Generates integers from start to maximum-1 diff --git a/migen/bank/eventmanager.py b/migen/bank/eventmanager.py index 298ec44a..200803ed 100644 --- a/migen/bank/eventmanager.py +++ b/migen/bank/eventmanager.py @@ -1,6 +1,6 @@ from migen.fhdl.structure import * from migen.bank.description import * -from migen.corelogic.misc import optree +from migen.genlib.misc import optree class EventSource: def __init__(self): diff --git a/migen/bus/asmibus.py b/migen/bus/asmibus.py index ff7b1927..cab327a7 100644 --- a/migen/bus/asmibus.py +++ b/migen/bus/asmibus.py @@ -1,5 +1,5 @@ from migen.fhdl.structure import * -from migen.corelogic.misc import optree +from migen.genlib.misc import optree from migen.bus.transactions import * from migen.sim.generic import Proxy, PureSimulable diff --git a/migen/bus/simple.py b/migen/bus/simple.py index 062b9e75..8c6e0d68 100644 --- a/migen/bus/simple.py +++ b/migen/bus/simple.py @@ -1,5 +1,5 @@ from migen.fhdl.structure import * -from migen.corelogic.misc import optree +from migen.genlib.misc import optree (S_TO_M, M_TO_S) = range(2) diff --git a/migen/bus/wishbone.py b/migen/bus/wishbone.py index fb7ec125..23abfa6e 100644 --- a/migen/bus/wishbone.py +++ b/migen/bus/wishbone.py @@ -1,7 +1,7 @@ from migen.fhdl.structure import * from migen.fhdl.specials import Memory -from migen.corelogic import roundrobin -from migen.corelogic.misc import optree +from migen.genlib import roundrobin +from migen.genlib.misc import optree from migen.bus.simple import * from migen.bus.transactions import * from migen.sim.generic import Proxy, PureSimulable diff --git a/migen/bus/wishbone2asmi.py b/migen/bus/wishbone2asmi.py index 0fccefcc..c68999cb 100644 --- a/migen/bus/wishbone2asmi.py +++ b/migen/bus/wishbone2asmi.py @@ -1,9 +1,9 @@ from migen.fhdl.structure import * from migen.fhdl.specials import Memory from migen.bus import wishbone -from migen.corelogic.fsm import FSM -from migen.corelogic.misc import split, displacer, chooser -from migen.corelogic.record import Record +from migen.genlib.fsm import FSM +from migen.genlib.misc import split, displacer, chooser +from migen.genlib.record import Record # cachesize (in 32-bit words) is the size of the data store, must be a power of 2 class WB2ASMI: diff --git a/migen/bus/wishbone2csr.py b/migen/bus/wishbone2csr.py index b8018662..5e62de84 100644 --- a/migen/bus/wishbone2csr.py +++ b/migen/bus/wishbone2csr.py @@ -1,7 +1,7 @@ from migen.bus import wishbone from migen.bus import csr from migen.fhdl.structure import * -from migen.corelogic.misc import timeline +from migen.genlib.misc import timeline class WB2CSR: def __init__(self): diff --git a/migen/corelogic/__init__.py b/migen/corelogic/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/migen/corelogic/buffers.py b/migen/corelogic/buffers.py deleted file mode 100644 index 29cee986..00000000 --- a/migen/corelogic/buffers.py +++ /dev/null @@ -1,87 +0,0 @@ -from migen.fhdl.structure import * - -class ReorderSlot: - def __init__(self, tag_width, data_width): - self.wait_data = Signal() - self.has_data = Signal() - self.tag = Signal(tag_width) - self.data = Signal(data_width) - -class ReorderBuffer: - def __init__(self, tag_width, data_width, depth): - self.depth = depth - - # issue - self.can_issue = Signal() - self.issue = Signal() - self.tag_issue = Signal(tag_width) - - # call - self.call = Signal() - self.tag_call = Signal(tag_width) - self.data_call = Signal(data_width) - - # readback - self.can_read = Signal() - self.read = Signal() - self.data_read = Signal(data_width) - - self._empty_count = Signal(max=self.depth+1, reset=self.depth) - self._produce = Signal(max=self.depth) - self._consume = Signal(max=self.depth) - self._slots = Array(ReorderSlot(tag_width, data_width) - for n in range(self.depth)) - - def get_fragment(self): - # issue - comb = [ - self.can_issue.eq(self._empty_count != 0) - ] - sync = [ - If(self.issue & self.can_issue, - self._empty_count.eq(self._empty_count - 1), - If(self._produce == self.depth - 1, - self._produce.eq(0) - ).Else( - self._produce.eq(self._produce + 1) - ), - self._slots[self._produce].wait_data.eq(1), - self._slots[self._produce].tag.eq(self.tag_issue) - ) - ] - - # call - for n, slot in enumerate(self._slots): - sync.append( - If(self.call & slot.wait_data & (self.tag_call == slot.tag), - slot.wait_data.eq(0), - slot.has_data.eq(1), - slot.data.eq(self.data_call) - ) - ) - - # readback - comb += [ - self.can_read.eq(self._slots[self._consume].has_data), - self.data_read.eq(self._slots[self._consume].data) - ] - sync += [ - If(self.read & self.can_read, - self._empty_count.eq(self._empty_count + 1), - If(self._consume == self.depth - 1, - self._consume.eq(0) - ).Else( - self._consume.eq(self._consume + 1) - ), - self._slots[self._consume].has_data.eq(0) - ) - ] - - # do not touch empty count when issuing and reading at the same time - sync += [ - If(self.issue & self.can_issue & self.read & self.can_read, - self._empty_count.eq(self._empty_count) - ) - ] - - return Fragment(comb, sync) diff --git a/migen/corelogic/complex.py b/migen/corelogic/complex.py deleted file mode 100644 index 34c98224..00000000 --- a/migen/corelogic/complex.py +++ /dev/null @@ -1,52 +0,0 @@ -from migen.fhdl.structure import * - -class Complex: - def __init__(self, real, imag): - self.real = real - self.imag = imag - - def __neg__(self): - return Complex(-self.real, -self.imag) - - def __add__(self, other): - if isinstance(other, Complex): - return Complex(self.real + other.real, self.imag + other.imag) - else: - return Complex(self.real + other, self.imag) - __radd__ = __add__ - def __sub__(self, other): - if isinstance(other, Complex): - return Complex(self.real - other.real, self.imag - other.imag) - else: - return Complex(self.real - other, self.imag) - def __rsub__(self, other): - if isinstance(other, Complex): - return Complex(other.real - self.real, other.imag - self.imag) - else: - return Complex(other - self.real, -self.imag) - def __mul__(self, other): - if isinstance(other, Complex): - return Complex(self.real*other.real - self.imag*other.imag, - self.real*other.imag + self.imag*other.real) - else: - return Complex(self.real*other, self.imag*other) - __rmul__ = __mul__ - - def __lshift__(self, other): - return Complex(self.real << other, self.imag << other) - def __rshift__(self, other): - return Complex(self.real >> other, self.imag >> other) - - def __repr__(self): - return repr(self.real) + " + " + repr(self.imag) + "j" - - def eq(self, r): - if isinstance(r, Complex): - return self.real.eq(r.real), self.imag.eq(r.imag) - else: - return self.real.eq(r), self.imag.eq(0) - -def SignalC(*args, **kwargs): - real = Signal(*args, **kwargs) - imag = Signal(*args, **kwargs) - return Complex(real, imag) diff --git a/migen/corelogic/divider.py b/migen/corelogic/divider.py deleted file mode 100644 index 62b87c21..00000000 --- a/migen/corelogic/divider.py +++ /dev/null @@ -1,42 +0,0 @@ -from migen.fhdl.structure import * - -class Divider: - def __init__(self, w): - self.w = w - - self.start_i = Signal() - self.dividend_i = Signal(w) - self.divisor_i = Signal(w) - self.ready_o = Signal() - self.quotient_o = Signal(w) - self.remainder_o = Signal(w) - - def get_fragment(self): - w = self.w - - qr = Signal(2*w) - counter = Signal(max=w+1) - divisor_r = Signal(w) - diff = Signal(w+1) - - comb = [ - self.quotient_o.eq(qr[:w]), - self.remainder_o.eq(qr[w:]), - self.ready_o.eq(counter == 0), - diff.eq(self.remainder_o - divisor_r) - ] - sync = [ - If(self.start_i, - counter.eq(w), - qr.eq(self.dividend_i), - divisor_r.eq(self.divisor_i) - ).Elif(~self.ready_o, - If(diff[w], - qr.eq(Cat(0, qr[:2*w-1])) - ).Else( - qr.eq(Cat(1, qr[:w-1], diff[:w])) - ), - counter.eq(counter - 1) - ) - ] - return Fragment(comb, sync) diff --git a/migen/corelogic/fsm.py b/migen/corelogic/fsm.py deleted file mode 100644 index 85f3a401..00000000 --- a/migen/corelogic/fsm.py +++ /dev/null @@ -1,41 +0,0 @@ -from migen.fhdl.structure import * - -class FSM: - def __init__(self, *states, delayed_enters=[]): - nstates = len(states) + sum([d[2] for d in delayed_enters]) - - self._state = Signal(max=nstates) - self._next_state = Signal(max=nstates) - for n, state in enumerate(states): - setattr(self, state, n) - self.actions = [[] for i in range(len(states))] - - for name, target, delay in delayed_enters: - target_state = getattr(self, target) - if delay: - name_state = len(self.actions) - setattr(self, name, name_state) - for i in range(delay-1): - self.actions.append([self.next_state(name_state+i+1)]) - self.actions.append([self.next_state(target_state)]) - else: - # alias - setattr(self, name, getattr(self, target_state)) - - def reset_state(self, state): - self._state.reset = state - - def next_state(self, state): - return self._next_state.eq(state) - - def act(self, state, *statements): - self.actions[state] += statements - - def get_fragment(self): - cases = dict((s, a) for s, a in enumerate(self.actions) if a) - comb = [ - self._next_state.eq(self._state), - Case(self._state, cases) - ] - sync = [self._state.eq(self._next_state)] - return Fragment(comb, sync) diff --git a/migen/corelogic/misc.py b/migen/corelogic/misc.py deleted file mode 100644 index fc0469db..00000000 --- a/migen/corelogic/misc.py +++ /dev/null @@ -1,80 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl.structure import _Operator - -def optree(op, operands, lb=None, ub=None, default=None): - if lb is None: - lb = 0 - if ub is None: - ub = len(operands) - l = ub - lb - if l == 0: - if default is None: - raise AttributeError - else: - return default - elif l == 1: - return operands[lb] - else: - s = lb + l//2 - return _Operator(op, - [optree(op, operands, lb, s, default), - optree(op, operands, s, ub, default)]) - -def split(v, *counts): - r = [] - offset = 0 - for n in counts: - r.append(v[offset:offset+n]) - offset += n - return tuple(r) - -def displacer(signal, shift, output, n=None, reverse=False): - if n is None: - n = 2**len(shift) - w = len(signal) - if reverse: - r = reversed(range(n)) - else: - r = range(n) - l = [Replicate(shift == i, w) & signal for i in r] - return output.eq(Cat(*l)) - -def chooser(signal, shift, output, n=None, reverse=False): - if n is None: - n = 2**len(shift) - w = len(output) - cases = {} - for i in range(n): - if reverse: - s = n - i - 1 - else: - s = i - cases[i] = [output.eq(signal[s*w:(s+1)*w])] - return Case(shift, cases).makedefault() - -def timeline(trigger, events): - lastevent = max([e[0] for e in events]) - counter = Signal(max=lastevent+1) - - counterlogic = If(counter != 0, - counter.eq(counter + 1) - ).Elif(trigger, - counter.eq(1) - ) - # insert counter reset if it doesn't naturally overflow - # (test if lastevent+1 is a power of 2) - if (lastevent & (lastevent + 1)) != 0: - counterlogic = If(counter == lastevent, - counter.eq(0) - ).Else( - counterlogic - ) - - def get_cond(e): - if e[0] == 0: - return trigger & (counter == 0) - else: - return counter == e[0] - sync = [If(get_cond(e), *e[1]) for e in events] - sync.append(counterlogic) - return sync diff --git a/migen/corelogic/record.py b/migen/corelogic/record.py deleted file mode 100644 index 74bd8303..00000000 --- a/migen/corelogic/record.py +++ /dev/null @@ -1,108 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl.tools import value_bits_sign - -class Record: - def __init__(self, layout, name=""): - self.name = name - self.field_order = [] - if self.name: - prefix = self.name + "_" - else: - prefix = "" - for f in layout: - if isinstance(f, tuple): - if isinstance(f[1], (int, tuple)): - setattr(self, f[0], Signal(f[1], prefix + f[0])) - elif isinstance(f[1], Signal) or isinstance(f[1], Record): - setattr(self, f[0], f[1]) - elif isinstance(f[1], list): - setattr(self, f[0], Record(f[1], prefix + f[0])) - else: - raise TypeError - if len(f) == 3: - self.field_order.append((f[0], f[2])) - else: - self.field_order.append((f[0], 1)) - else: - setattr(self, f, Signal(1, prefix + f)) - self.field_order.append((f, 1)) - - def layout(self): - l = [] - for key, alignment in self.field_order: - e = self.__dict__[key] - if isinstance(e, Signal): - l.append((key, (e.nbits, e.signed), alignment)) - elif isinstance(e, Record): - l.append((key, e.layout(), alignment)) - return l - - def copy(self, name=None): - return Record(self.layout(), name) - - def get_alignment(self, name): - return list(filter(lambda x: x[0] == name, self.field_order))[0][1] - - def subrecord(self, *descr): - fields = [] - for item in descr: - path = item.split("/") - last = path.pop() - pos_self = self - pos_fields = fields - for hop in path: - pos_self = getattr(pos_self, hop) - lu = list(filter(lambda x: x[0] == hop, pos_fields)) - try: - pos_fields = lu[0][1] - except IndexError: - n = [] - pos_fields.append((hop, n)) - pos_fields = n - if not isinstance(pos_fields, list): - raise ValueError - if len(list(filter(lambda x: x[0] == last, pos_fields))) > 0: - raise ValueError - pos_fields.append((last, getattr(pos_self, last), pos_self.get_alignment(last))) - return Record(fields, "subrecord") - - def compatible(self, other): - tpl1 = self.flatten() - tpl2 = other.flatten() - return len(tpl1) == len(tpl2) - - def flatten(self, align=False, offset=0, return_offset=False): - l = [] - for key, alignment in self.field_order: - if align: - pad_size = alignment - (offset % alignment) - if pad_size < alignment: - l.append(Replicate(0, pad_size)) - offset += pad_size - - e = self.__dict__[key] - if isinstance(e, Signal): - added = [e] - elif isinstance(e, Record): - added = e.flatten(align, offset) - else: - raise TypeError - for x in added: - offset += value_bits_sign(x)[0] - l += added - if return_offset: - return (l, offset) - else: - return l - - def to_signal(self, assignment_list, sig_out, align=False): - flattened, length = self.flatten(align, return_offset=True) - raw = Signal(length) - if sig_out: - assignment_list.append(raw.eq(Cat(*flattened))) - else: - assignment_list.append(Cat(*flattened).eq(raw)) - return raw - - def __repr__(self): - return "" diff --git a/migen/corelogic/roundrobin.py b/migen/corelogic/roundrobin.py deleted file mode 100644 index f55b3fee..00000000 --- a/migen/corelogic/roundrobin.py +++ /dev/null @@ -1,38 +0,0 @@ -from migen.fhdl.structure import * - -(SP_WITHDRAW, SP_CE) = range(2) - -class RoundRobin: - def __init__(self, n, switch_policy=SP_WITHDRAW): - self.n = n - self.request = Signal(self.n) - self.grant = Signal(max=self.n) - self.switch_policy = switch_policy - if self.switch_policy == SP_CE: - self.ce = Signal() - - def get_fragment(self): - if self.n > 1: - cases = {} - for i in range(self.n): - switch = [] - for j in reversed(range(i+1,i+self.n)): - t = j % self.n - switch = [ - If(self.request[t], - self.grant.eq(t) - ).Else( - *switch - ) - ] - if self.switch_policy == SP_WITHDRAW: - case = [If(~self.request[i], *switch)] - else: - case = switch - cases[i] = case - statement = Case(self.grant, cases) - if self.switch_policy == SP_CE: - statement = If(self.ce, statement) - return Fragment(sync=[statement]) - else: - return Fragment([self.grant.eq(0)]) diff --git a/migen/flow/actor.py b/migen/flow/actor.py index 15eee8c2..ce46638d 100644 --- a/migen/flow/actor.py +++ b/migen/flow/actor.py @@ -1,6 +1,6 @@ from migen.fhdl.structure import * -from migen.corelogic.misc import optree -from migen.corelogic.record import * +from migen.genlib.misc import optree +from migen.genlib.record import * class Endpoint: def __init__(self, token): diff --git a/migen/flow/network.py b/migen/flow/network.py index 494d906e..df739eef 100644 --- a/migen/flow/network.py +++ b/migen/flow/network.py @@ -1,7 +1,7 @@ from networkx import MultiDiGraph from migen.fhdl.structure import * -from migen.corelogic.misc import optree +from migen.genlib.misc import optree from migen.flow.actor import * from migen.flow import plumbing from migen.flow.isd import DFGReporter diff --git a/migen/flow/plumbing.py b/migen/flow/plumbing.py index 7c30f760..04fc5d12 100644 --- a/migen/flow/plumbing.py +++ b/migen/flow/plumbing.py @@ -1,7 +1,7 @@ from migen.fhdl.structure import * from migen.flow.actor import * -from migen.corelogic.record import * -from migen.corelogic.misc import optree +from migen.genlib.record import * +from migen.genlib.misc import optree class Buffer(PipelinedActor): def __init__(self, layout): diff --git a/migen/genlib/__init__.py b/migen/genlib/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/migen/genlib/buffers.py b/migen/genlib/buffers.py new file mode 100644 index 00000000..29cee986 --- /dev/null +++ b/migen/genlib/buffers.py @@ -0,0 +1,87 @@ +from migen.fhdl.structure import * + +class ReorderSlot: + def __init__(self, tag_width, data_width): + self.wait_data = Signal() + self.has_data = Signal() + self.tag = Signal(tag_width) + self.data = Signal(data_width) + +class ReorderBuffer: + def __init__(self, tag_width, data_width, depth): + self.depth = depth + + # issue + self.can_issue = Signal() + self.issue = Signal() + self.tag_issue = Signal(tag_width) + + # call + self.call = Signal() + self.tag_call = Signal(tag_width) + self.data_call = Signal(data_width) + + # readback + self.can_read = Signal() + self.read = Signal() + self.data_read = Signal(data_width) + + self._empty_count = Signal(max=self.depth+1, reset=self.depth) + self._produce = Signal(max=self.depth) + self._consume = Signal(max=self.depth) + self._slots = Array(ReorderSlot(tag_width, data_width) + for n in range(self.depth)) + + def get_fragment(self): + # issue + comb = [ + self.can_issue.eq(self._empty_count != 0) + ] + sync = [ + If(self.issue & self.can_issue, + self._empty_count.eq(self._empty_count - 1), + If(self._produce == self.depth - 1, + self._produce.eq(0) + ).Else( + self._produce.eq(self._produce + 1) + ), + self._slots[self._produce].wait_data.eq(1), + self._slots[self._produce].tag.eq(self.tag_issue) + ) + ] + + # call + for n, slot in enumerate(self._slots): + sync.append( + If(self.call & slot.wait_data & (self.tag_call == slot.tag), + slot.wait_data.eq(0), + slot.has_data.eq(1), + slot.data.eq(self.data_call) + ) + ) + + # readback + comb += [ + self.can_read.eq(self._slots[self._consume].has_data), + self.data_read.eq(self._slots[self._consume].data) + ] + sync += [ + If(self.read & self.can_read, + self._empty_count.eq(self._empty_count + 1), + If(self._consume == self.depth - 1, + self._consume.eq(0) + ).Else( + self._consume.eq(self._consume + 1) + ), + self._slots[self._consume].has_data.eq(0) + ) + ] + + # do not touch empty count when issuing and reading at the same time + sync += [ + If(self.issue & self.can_issue & self.read & self.can_read, + self._empty_count.eq(self._empty_count) + ) + ] + + return Fragment(comb, sync) diff --git a/migen/genlib/complex.py b/migen/genlib/complex.py new file mode 100644 index 00000000..34c98224 --- /dev/null +++ b/migen/genlib/complex.py @@ -0,0 +1,52 @@ +from migen.fhdl.structure import * + +class Complex: + def __init__(self, real, imag): + self.real = real + self.imag = imag + + def __neg__(self): + return Complex(-self.real, -self.imag) + + def __add__(self, other): + if isinstance(other, Complex): + return Complex(self.real + other.real, self.imag + other.imag) + else: + return Complex(self.real + other, self.imag) + __radd__ = __add__ + def __sub__(self, other): + if isinstance(other, Complex): + return Complex(self.real - other.real, self.imag - other.imag) + else: + return Complex(self.real - other, self.imag) + def __rsub__(self, other): + if isinstance(other, Complex): + return Complex(other.real - self.real, other.imag - self.imag) + else: + return Complex(other - self.real, -self.imag) + def __mul__(self, other): + if isinstance(other, Complex): + return Complex(self.real*other.real - self.imag*other.imag, + self.real*other.imag + self.imag*other.real) + else: + return Complex(self.real*other, self.imag*other) + __rmul__ = __mul__ + + def __lshift__(self, other): + return Complex(self.real << other, self.imag << other) + def __rshift__(self, other): + return Complex(self.real >> other, self.imag >> other) + + def __repr__(self): + return repr(self.real) + " + " + repr(self.imag) + "j" + + def eq(self, r): + if isinstance(r, Complex): + return self.real.eq(r.real), self.imag.eq(r.imag) + else: + return self.real.eq(r), self.imag.eq(0) + +def SignalC(*args, **kwargs): + real = Signal(*args, **kwargs) + imag = Signal(*args, **kwargs) + return Complex(real, imag) diff --git a/migen/genlib/divider.py b/migen/genlib/divider.py new file mode 100644 index 00000000..62b87c21 --- /dev/null +++ b/migen/genlib/divider.py @@ -0,0 +1,42 @@ +from migen.fhdl.structure import * + +class Divider: + def __init__(self, w): + self.w = w + + self.start_i = Signal() + self.dividend_i = Signal(w) + self.divisor_i = Signal(w) + self.ready_o = Signal() + self.quotient_o = Signal(w) + self.remainder_o = Signal(w) + + def get_fragment(self): + w = self.w + + qr = Signal(2*w) + counter = Signal(max=w+1) + divisor_r = Signal(w) + diff = Signal(w+1) + + comb = [ + self.quotient_o.eq(qr[:w]), + self.remainder_o.eq(qr[w:]), + self.ready_o.eq(counter == 0), + diff.eq(self.remainder_o - divisor_r) + ] + sync = [ + If(self.start_i, + counter.eq(w), + qr.eq(self.dividend_i), + divisor_r.eq(self.divisor_i) + ).Elif(~self.ready_o, + If(diff[w], + qr.eq(Cat(0, qr[:2*w-1])) + ).Else( + qr.eq(Cat(1, qr[:w-1], diff[:w])) + ), + counter.eq(counter - 1) + ) + ] + return Fragment(comb, sync) diff --git a/migen/genlib/fsm.py b/migen/genlib/fsm.py new file mode 100644 index 00000000..85f3a401 --- /dev/null +++ b/migen/genlib/fsm.py @@ -0,0 +1,41 @@ +from migen.fhdl.structure import * + +class FSM: + def __init__(self, *states, delayed_enters=[]): + nstates = len(states) + sum([d[2] for d in delayed_enters]) + + self._state = Signal(max=nstates) + self._next_state = Signal(max=nstates) + for n, state in enumerate(states): + setattr(self, state, n) + self.actions = [[] for i in range(len(states))] + + for name, target, delay in delayed_enters: + target_state = getattr(self, target) + if delay: + name_state = len(self.actions) + setattr(self, name, name_state) + for i in range(delay-1): + self.actions.append([self.next_state(name_state+i+1)]) + self.actions.append([self.next_state(target_state)]) + else: + # alias + setattr(self, name, getattr(self, target_state)) + + def reset_state(self, state): + self._state.reset = state + + def next_state(self, state): + return self._next_state.eq(state) + + def act(self, state, *statements): + self.actions[state] += statements + + def get_fragment(self): + cases = dict((s, a) for s, a in enumerate(self.actions) if a) + comb = [ + self._next_state.eq(self._state), + Case(self._state, cases) + ] + sync = [self._state.eq(self._next_state)] + return Fragment(comb, sync) diff --git a/migen/genlib/misc.py b/migen/genlib/misc.py new file mode 100644 index 00000000..fc0469db --- /dev/null +++ b/migen/genlib/misc.py @@ -0,0 +1,80 @@ +from migen.fhdl.structure import * +from migen.fhdl.structure import _Operator + +def optree(op, operands, lb=None, ub=None, default=None): + if lb is None: + lb = 0 + if ub is None: + ub = len(operands) + l = ub - lb + if l == 0: + if default is None: + raise AttributeError + else: + return default + elif l == 1: + return operands[lb] + else: + s = lb + l//2 + return _Operator(op, + [optree(op, operands, lb, s, default), + optree(op, operands, s, ub, default)]) + +def split(v, *counts): + r = [] + offset = 0 + for n in counts: + r.append(v[offset:offset+n]) + offset += n + return tuple(r) + +def displacer(signal, shift, output, n=None, reverse=False): + if n is None: + n = 2**len(shift) + w = len(signal) + if reverse: + r = reversed(range(n)) + else: + r = range(n) + l = [Replicate(shift == i, w) & signal for i in r] + return output.eq(Cat(*l)) + +def chooser(signal, shift, output, n=None, reverse=False): + if n is None: + n = 2**len(shift) + w = len(output) + cases = {} + for i in range(n): + if reverse: + s = n - i - 1 + else: + s = i + cases[i] = [output.eq(signal[s*w:(s+1)*w])] + return Case(shift, cases).makedefault() + +def timeline(trigger, events): + lastevent = max([e[0] for e in events]) + counter = Signal(max=lastevent+1) + + counterlogic = If(counter != 0, + counter.eq(counter + 1) + ).Elif(trigger, + counter.eq(1) + ) + # insert counter reset if it doesn't naturally overflow + # (test if lastevent+1 is a power of 2) + if (lastevent & (lastevent + 1)) != 0: + counterlogic = If(counter == lastevent, + counter.eq(0) + ).Else( + counterlogic + ) + + def get_cond(e): + if e[0] == 0: + return trigger & (counter == 0) + else: + return counter == e[0] + sync = [If(get_cond(e), *e[1]) for e in events] + sync.append(counterlogic) + return sync diff --git a/migen/genlib/record.py b/migen/genlib/record.py new file mode 100644 index 00000000..74bd8303 --- /dev/null +++ b/migen/genlib/record.py @@ -0,0 +1,108 @@ +from migen.fhdl.structure import * +from migen.fhdl.tools import value_bits_sign + +class Record: + def __init__(self, layout, name=""): + self.name = name + self.field_order = [] + if self.name: + prefix = self.name + "_" + else: + prefix = "" + for f in layout: + if isinstance(f, tuple): + if isinstance(f[1], (int, tuple)): + setattr(self, f[0], Signal(f[1], prefix + f[0])) + elif isinstance(f[1], Signal) or isinstance(f[1], Record): + setattr(self, f[0], f[1]) + elif isinstance(f[1], list): + setattr(self, f[0], Record(f[1], prefix + f[0])) + else: + raise TypeError + if len(f) == 3: + self.field_order.append((f[0], f[2])) + else: + self.field_order.append((f[0], 1)) + else: + setattr(self, f, Signal(1, prefix + f)) + self.field_order.append((f, 1)) + + def layout(self): + l = [] + for key, alignment in self.field_order: + e = self.__dict__[key] + if isinstance(e, Signal): + l.append((key, (e.nbits, e.signed), alignment)) + elif isinstance(e, Record): + l.append((key, e.layout(), alignment)) + return l + + def copy(self, name=None): + return Record(self.layout(), name) + + def get_alignment(self, name): + return list(filter(lambda x: x[0] == name, self.field_order))[0][1] + + def subrecord(self, *descr): + fields = [] + for item in descr: + path = item.split("/") + last = path.pop() + pos_self = self + pos_fields = fields + for hop in path: + pos_self = getattr(pos_self, hop) + lu = list(filter(lambda x: x[0] == hop, pos_fields)) + try: + pos_fields = lu[0][1] + except IndexError: + n = [] + pos_fields.append((hop, n)) + pos_fields = n + if not isinstance(pos_fields, list): + raise ValueError + if len(list(filter(lambda x: x[0] == last, pos_fields))) > 0: + raise ValueError + pos_fields.append((last, getattr(pos_self, last), pos_self.get_alignment(last))) + return Record(fields, "subrecord") + + def compatible(self, other): + tpl1 = self.flatten() + tpl2 = other.flatten() + return len(tpl1) == len(tpl2) + + def flatten(self, align=False, offset=0, return_offset=False): + l = [] + for key, alignment in self.field_order: + if align: + pad_size = alignment - (offset % alignment) + if pad_size < alignment: + l.append(Replicate(0, pad_size)) + offset += pad_size + + e = self.__dict__[key] + if isinstance(e, Signal): + added = [e] + elif isinstance(e, Record): + added = e.flatten(align, offset) + else: + raise TypeError + for x in added: + offset += value_bits_sign(x)[0] + l += added + if return_offset: + return (l, offset) + else: + return l + + def to_signal(self, assignment_list, sig_out, align=False): + flattened, length = self.flatten(align, return_offset=True) + raw = Signal(length) + if sig_out: + assignment_list.append(raw.eq(Cat(*flattened))) + else: + assignment_list.append(Cat(*flattened).eq(raw)) + return raw + + def __repr__(self): + return "" diff --git a/migen/genlib/roundrobin.py b/migen/genlib/roundrobin.py new file mode 100644 index 00000000..f55b3fee --- /dev/null +++ b/migen/genlib/roundrobin.py @@ -0,0 +1,38 @@ +from migen.fhdl.structure import * + +(SP_WITHDRAW, SP_CE) = range(2) + +class RoundRobin: + def __init__(self, n, switch_policy=SP_WITHDRAW): + self.n = n + self.request = Signal(self.n) + self.grant = Signal(max=self.n) + self.switch_policy = switch_policy + if self.switch_policy == SP_CE: + self.ce = Signal() + + def get_fragment(self): + if self.n > 1: + cases = {} + for i in range(self.n): + switch = [] + for j in reversed(range(i+1,i+self.n)): + t = j % self.n + switch = [ + If(self.request[t], + self.grant.eq(t) + ).Else( + *switch + ) + ] + if self.switch_policy == SP_WITHDRAW: + case = [If(~self.request[i], *switch)] + else: + case = switch + cases[i] = case + statement = Case(self.grant, cases) + if self.switch_policy == SP_CE: + statement = If(self.ce, statement) + return Fragment(sync=[statement]) + else: + return Fragment([self.grant.eq(0)]) diff --git a/migen/pytholite/fsm.py b/migen/pytholite/fsm.py index 305a0cd4..7bc6c4c2 100644 --- a/migen/pytholite/fsm.py +++ b/migen/pytholite/fsm.py @@ -1,5 +1,5 @@ from migen.fhdl import visit as fhdl -from migen.corelogic.fsm import FSM +from migen.genlib.fsm import FSM class AbstractNextState: def __init__(self, target_state):