from nmigen import Module, Signal, Cat, Elaboratable
from nmigen.cli import main, verilog
-from ieee754.fpcommon.fpbase import FPNumBaseRecord
+from ieee754.fpcommon.fpbase import (FPNumBaseRecord, Overflow)
from ieee754.fpcommon.fpbase import FPState
from ieee754.fpcommon.denorm import FPSCData
self.z = FPNumBaseRecord(width, False)
self.out_do_z = Signal(reset_less=True)
self.oz = Signal(width, reset_less=True)
+ self.of = Overflow()
# TODO: here is where Q and R would be put, and passed
# down to Stage1 processing.
def eq(self, i):
return [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz),
+ self.of.eq(i.of),
self.product.eq(i.product), self.mid.eq(i.mid)]
class FPDivStages(FPState, SimpleHandshake):
- def __init__(self, width, id_wid):
+ def __init__(self, width, id_wid, n_stages, begin, end):
FPState.__init__(self, "align")
self.width = width
self.id_wid = id_wid
+ self.n_stages = n_stages # number of combinatorial stages
+ self.begin = begin # "begin" mode
+ self.end = end # "end" mode
SimpleHandshake.__init__(self, self) # pipeline is its own stage
self.m1o = self.ospec()
def ispec(self):
- return FPSCData(self.width, self.id_wid, False)
+ if self.begin:
+ return FPSCData(self.width, self.id_wid, False)
+ return FPAddStage1Data(self.width, self.id_wid) # AddStage1 ospec
def ospec(self):
+ if self.end: # TODO
+ return FPAddStage1Data(self.width, self.id_wid) # AddStage1 ospec
return FPAddStage1Data(self.width, self.id_wid) # AddStage1 ospec
def setup(self, m, i):
""" links module to inputs and outputs
"""
- # TODO. clearly, this would be a for-loop, here, creating
- # a huge number of stages (if radix-2 is used). interestingly
- # the number of stages will be data-dependent.
- divstages = [FPDivStage0Mod(self.width, self.id_wid)]
- for i in range(self.width): # XXX TODO: work out actual number needed
+ # start mode accepts data from the FP normalisation stage
+ # and does a bit of munging of the data. it will be chained
+ # into the first DIV combinatorial block,
+
+ # end mode takes the DIV pipeline/chain data and munges it
+ # into the format that the normalisation can accept.
+
+ divstages = []
+
+ if self.begin: # XXX check this
+ divstages.append(FPDivStage0Mod(self.width, self.id_wid))
+
+ for count in range(self.n_stages): # number of combinatorial stages
divstages.append(FPDivStage1Mod(self.width, self.id_wid))
- divstages.append(FPDivStage2Mod(self.width, self.id_wid))
+
+ if self.end: # XXX check this
+ divstages.append(FPDivStage2Mod(self.width, self.id_wid))
chain = StageChain(divstages)
chain.setup(m, i)
- self.o = m1mod.o
+ # output is from the last pipe stage
+ self.o = divstages[-1].o
def process(self, i):
return self.o
class FPDIVBasePipe(ControlBase):
def __init__(self, width, id_wid):
ControlBase.__init__(self)
- self.pipe1 = FPDIVSpecialCasesDeNorm(width, id_wid)
- self.pipe2 = FPDivStages(width, id_wid)
- self.pipe3 = FPNormToPack(width, id_wid)
+ self.pipestart = FPDIVSpecialCasesDeNorm(width, id_wid)
+ pipechain = []
+ n_stages = 6 # TODO
+ n_combinatorial_stages = 2 # TODO
+ for i in range(n_stages):
+ begin = i == 0 # needs to convert input from pipestart ospec
+ end = i == n_stages - 1 # needs to convert output to pipeend ispec
+ pipechain.append(FPDivStages(width, id_wid,
+ n_combinatorial_stages,
+ begin, end))
+ self.pipechain = pipechain
+ self.pipeend = FPNormToPack(width, id_wid)
- self._eqs = self.connect([self.pipe1, self.pipe2, self.pipe3])
+ self._eqs = self.connect([self.pipestart] + pipechain + [self.pipeend])
def elaborate(self, platform):
m = ControlBase.elaborate(self, platform)
- m.submodules.scnorm = self.pipe1
- m.submodules.divstages = self.pipe2
- m.submodules.normpack = self.pipe3
+ m.submodules.scnorm = self.pipestart
+ for i, p in enumerate(self.pipechain):
+ setattr(m.submodules, "pipediv%d" % i, p)
+ m.submodules.normpack = self.pipeend
m.d.comb += self._eqs
return m