Initial import, FHDL basic structure, divider example
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 4 Dec 2011 15:44:38 +0000 (16:44 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 4 Dec 2011 15:44:38 +0000 (16:44 +0100)
.gitignore [new file with mode: 0644]
migen/__init__.py [new file with mode: 0644]
migen/fhdl/__init__.py [new file with mode: 0644]
migen/fhdl/structure.py [new file with mode: 0644]
test.py [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..8d35cb3
--- /dev/null
@@ -0,0 +1,2 @@
+__pycache__
+*.pyc
diff --git a/migen/__init__.py b/migen/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/migen/fhdl/__init__.py b/migen/fhdl/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/migen/fhdl/structure.py b/migen/fhdl/structure.py
new file mode 100644 (file)
index 0000000..cdaf48c
--- /dev/null
@@ -0,0 +1,207 @@
+import math
+
+def BitsFor(n):
+       if n == 0:
+               return 1
+       else:
+               return int(math.ceil(math.log(n+1, 2)))
+
+class BV:
+       def __init__(self, width=1, signed=False):
+               self.width = width
+               self.signed = signed
+       
+       def __str__(self):
+               r = str(self.width) + "'"
+               if self.signed:
+                       r += "s"
+               r += "d"
+               return r
+
+class Value:
+       def __init__(self, bv):
+               self.bv = bv
+       
+       def __add__(self, other):
+               return Operator("+", [self, other])
+       def __radd__(self, other):
+               return Operator("+", [other, self])
+       def __sub__(self, other):
+               return Operator("-", [self, other])
+       def __rsub__(self, other):
+               return Operator("-", [other, self])
+       def __mul__(self, other):
+               return Operator("*", [self, other])
+       def __rmul__(self, other):
+               return Operator("*", [other, self])
+       def __lshift__(self, other):
+               return Operator("<<", [self, other])
+       def __rlshift__(self, other):
+               return Operator("<<", [other, self])
+       def __rshift__(self, other):
+               return Operator(">>", [self, other])
+       def __rrshift__(self, other):
+               return Operator(">>", [other, self])
+       def __and__(self, other):
+               return Operator("&", [self, other])
+       def __rand__(self, other):
+               return Operator("&", [other, self])
+       def __xor__(self, other):
+               return Operator("^", [self, other])
+       def __rxor__(self, other):
+               return Operator("^", [other, self])
+       def __or__(self, other):
+               return Operator("|", [self, other])
+       def __ror__(self, other):
+               return Operator("|", [other, self])
+       
+       def __lt__(self, other):
+               return Operator("<", [self, other])
+       def __le__(self, other):
+               return Operator("<=", [self, other])
+       def __eq__(self, other):
+               return Operator("==", [self, other])
+       def __ne__(self, other):
+               return Operator("!=", [self, other])
+       def __gt__(self, other):
+               return Operator(">", [self, other])
+       def __ge__(self, other):
+               return Operator(">=", [self, other])
+       
+       
+       def __getitem__(self, key):
+               if isinstance(key, int):
+                       return Slice(self, key, key+1)
+               elif isinstance(key, slice):
+                       start = key.start or 0
+                       stop = key.stop or self.bv.width
+                       if key.step != None:
+                               raise KeyError
+                       return Slice(self, start, stop)
+               else:
+                       raise KeyError
+
+class Operator(Value):
+       def __init__(self, op, operands):
+               self.op = op
+               self.operands = list(map(_cst, operands))
+       
+       def __str__(self):
+               arity = len(self.operands)
+               if arity == 1:
+                       r = self.op + str(self.operands[0])
+               elif arity == 2:
+                       r = str(self.operands[0]) + " " + self.op + " " + str(self.operands[1])
+               else:
+                       r = self.op + "(" + ", ".join(map(str, self.operands)) + ")"
+               return "(" + r + ")"
+
+class Slice(Value):
+       def __init__(self, value, start, stop):
+               self.value = value
+               self.start = start
+               self.stop = stop
+       
+       def __str__(self):
+               if self.start + 1 == self.stop:
+                       sr = "[" + str(self.start) + "]"
+               else:
+                       sr = "[" + str(self.start) + ":" + str(self.stop) + "]"
+               return str(self.value) + sr
+
+class Cat(Value):
+       def __init__(self, *args):
+               self.l = list(map(_cst, args))
+       
+       def __str__(self):
+               return "{" + ", ".join(map(str, self.l)) + "}"
+
+class Constant(Value):
+       def __init__(self, n, bv=None):
+               if bv == None:
+                       Value.__init__(self, BV(BitsFor(n)))
+               else:
+                       Value.__init__(self, bv)
+               self.n = n
+       
+       def __str__(self):
+               if self.n >= 0:
+                       return str(self.bv) + str(self.n)
+               else:
+                       return "-" + str(self.bv) + str(-self.n)
+
+def _cst(x):
+       if isinstance(x, int):
+               return Constant(x)
+       else:
+               return x
+
+class Signal(Value):
+       def __init__(self, bv=BV(), name="anonymous", variable=False, reset=0):
+               Value.__init__(self, bv)
+               self.bv = bv
+               self.variable = variable
+               self.name = name
+               self.reset = Constant(reset, bv)
+
+       def __str__(self):
+               return self.name
+
+def Declare(parent, name, bv=BV(), variable=False, reset=0):
+       setattr(parent, name, Signal(bv, parent.__class__.__name__+"_"+name, variable, reset))
+
+# statements
+
+class Assign:
+       def __init__(self, l, r):
+               self.l = l
+               self.r = _cst(r)
+       
+       def __str__(self):
+               return str(self.l) + " = " + str(self.r)
+
+class StatementList:
+       def __init__(self, l=[]):
+               self.l = l
+       
+       def __str__(self):
+               return "\n".join(map(str, self.l))
+
+def _sl(x):
+       if isinstance(x, list):
+               return StatementList(x)
+       else:
+               return x
+
+def _indent(s):
+       if s:
+               return "\t" + s.replace("\n", "\n\t")
+       else:
+               return ""
+
+class If:
+       def __init__(self, cond, t, f=StatementList()):
+               self.cond = cond
+               self.t = _sl(t)
+               self.f = _sl(f)
+       
+       def __str__(self):
+               r = "if " + str(self.cond) + ":\n" + _indent(str(self.t))
+               if self.f.l:
+                       r += "\nelse:\n" + _indent(str(self.f))
+               return r
+
+class Case:
+       def __init__(self, test, cases=[]):
+               self.test = test
+               self.cases = cases
+
+#
+
+class Fragment:
+       def __init__(self, comb=StatementList(), sync=StatementList()):
+               self.comb = _sl(comb)
+               self.sync = _sl(sync)
+       
+       def __str__(self):
+               return "Comb:\n" + _indent(str(self.comb)) + "\nSync:\n" + _indent(str(self.sync))
\ No newline at end of file
diff --git a/test.py b/test.py
new file mode 100644 (file)
index 0000000..9a0f136
--- /dev/null
+++ b/test.py
@@ -0,0 +1,48 @@
+from migen.fhdl import structure as f
+from functools import partial
+
+class Divider:
+       def __init__(self, w):
+               self.w = w
+               
+               d = partial(f.Declare, self)
+               
+               d("start_i")
+               d("dividend_i", f.BV(w))
+               d("divisor_i", f.BV(w))
+               d("ready_o")
+               d("quotient_o", f.BV(w))
+               d("remainder_o", f.BV(w))
+               
+               d("_qr", f.BV(2*w))
+               d("_counter", f.BV(f.BitsFor(w)))
+               d("_divisor_r", f.BV(w))
+               d("_diff", f.BV(w+1))
+       
+       def GetFragment(self):
+               a = f.Assign
+               comb = [
+                       a(self.quotient_o, self._qr[:self.w]),
+                       a(self.remainder_o, self._qr[self.w:]),
+                       a(self.ready_o, self._counter == f.Constant(0, self._counter.bv)),
+                       a(self._diff, self.remainder_o - self._divisor_r)
+               ]
+               sync = [
+                       f.If(self.start_i == 1, [
+                               a(self._counter, self.w),
+                               a(self._qr, self.dividend_i),
+                               a(self._divisor_r, self.divisor_i)
+                       ], [
+                               f.If(self.ready_o == 0, [
+                                       f.If(self._diff[self.w] == 1,
+                                               [a(self._qr, f.Cat(0, self._qr[:2*self.w-1]))],
+                                               [a(self._qr, f.Cat(1, self._qr[:self.w-1], self._diff[:self.w]))]),
+                                       a(self._counter, self._counter - f.Constant(1, self._counter.bv)),
+                               ])
+                       ])
+               ]
+               return f.Fragment(comb, sync)
+
+d = Divider(32)
+f = d.GetFragment()
+print(f)
\ No newline at end of file