[libre-riscv-dev] div/mod algorithm written in python
Luke Kenneth Casson Leighton
lkcl at lkcl.net
Sun Jul 21 16:33:21 BST 2019
i added in the "stage_index" parameter which should now finally start
to make it clear for you what's going on.
the stage_index is computed back in ieee754/fpdiv/pipeline.py, which
is where the "construction" takes place, and it has three modes.
first mode adds in a "FPDivStagesSetup" as the first StageChained
"thing", the others will be "FPDivStagesIntermediate"s. pipes in the
middle are only made from a StageChain of intermediaries. last one
has a Final at the end of the StageChain.
the fact that the "stage_index" gets passed around should give you a
"handle" on how this fits together, as it's the first piece of
"config" data that is in place.
l.
class FPDivStagesSetup(FPState, SimpleHandshake):
- def __init__(self, pspec, n_stages):
+ def __init__(self, pspec, n_stages, stage_offs):
FPState.__init__(self, "divsetup")
self.pspec = pspec
self.n_stages = n_stages # number of combinatorial stages
+ self.stage_offs = stage_offs # each CalcStage needs *absolute* idx
SimpleHandshake.__init__(self, self) # pipeline is its own stage
self.m1o = self.ospec()
@@ -54,11 +55,12 @@ class FPDivStagesSetup(FPState, SimpleHandshake):
divstages.append(DivPipeSetupStage(self.pspec))
# here is where the intermediary stages are added.
- # n_stages is adjusted (in pipeline.py), reduced to take
- # into account the extra processing that self.begin and self.end
- # will add.
+ # n_stages is adjusted (by pipeline.py), reduced to take
+ # into account extra processing that FPDivStage0Mod and DivPipeSetup
+ # might add.
for count in range(self.n_stages): # number of combinatorial stages
- divstages.append(DivPipeCalculateStage(self.pspec, count))
+ idx = count + self.stage_offs
+ divstages.append(DivPipeCalculateStage(self.pspec, idx))
On Sun, Jul 21, 2019 at 4:20 PM Luke Kenneth Casson Leighton
<lkcl at lkcl.net> wrote:
>
> this is the *last* piece of the puzzle - where quotient_root gets
> dropped into the mantissa of z (where, previously the z mantissa field
> has *not* been touched, at all, in *any* of the previous pipeline
> stages), and the "remainder" is simply used to calculate the sticky
> bit.
>
> now, this *might* require instead that the MSB of the remainder goes
> into "guard", and MSB-1 goes into "round", and remainder[:-2].bool()
> goes into the sticky, i honestly don't know, and i don't know if it
> even matters.
>
> what the code below does, is it assumes that there are 2 extra bits on
> the mantissa, one is "guard" and the other is "round". anything
> "spare" at the beginning of the quotient_root (if it wasn't "designed"
> to be *exactly* the right length) will be used for "sticky".
>
> this isn't perfect, by any means: it's just to give you the general idea, ok?
>
> however, the point is to illustrate that there *really is* no need to
> do any "extra development", i *really have* laid the groundwork
> already and it *really is* just a simple matter of connecting things
> together.
>
> no need to do exponent shifting, no need to do de-normalisation, no
> need to do re-normalisation, alignment, conversion: nothing. the
> *only* thing(s) needed are to sort out the operator, the conversion of
> pspec into config, and so on.
>
> l.
>
>
> index 8db281a..9e36cb2 100644
> --- a/src/ieee754/fpdiv/div2.py
> +++ b/src/ieee754/fpdiv/div2.py
> @@ -21,8 +21,7 @@ class FPDivStage2Mod(FPState, Elaboratable):
> self.o = self.ospec()
>
> def ispec(self):
> - # TODO: DivPipeCoreInterstageData
> - return FPDivStage0Data(self.pspec) # Q/Rem in...
> + return DivPipeOutputData(self.pspec) # Q/Rem in...
>
> def ospec(self):
> # XXX REQUIRED. MUST NOT BE CHANGED. this is the format
> @@ -58,11 +57,11 @@ class FPDivStage2Mod(FPState, Elaboratable):
> with m.If(~self.i.out_do_z):
> mw = self.o.z.m_width
> m.d.comb += [
> - self.o.z.m.eq(self.i.product[mw+2:]),
> - self.o.of.m0.eq(self.i.product[mw+2]),
> - self.o.of.guard.eq(self.i.product[mw+1]),
> - self.o.of.round_bit.eq(self.i.product[mw]),
> - self.o.of.sticky.eq(self.i.product[0:mw].bool())
> + self.o.z.m.eq(self.i.quotient_root[mw+2:]),
> + self.o.of.m0.eq(self.i.quotient_root[mw+2]), # copy of LSB
> + self.o.of.guard.eq(self.i.quotient_root[mw+1]),
> + self.o.of.round_bit.eq(self.i.quotient_root[mw]),
> + self.o.of.sticky.eq(Cat(self.i.remainder,
> + self.i.quotient_root[:mw]).bool())
>
> ]
>
> m.d.comb += self.o.out_do_z.eq(self.i.out_do_z)
>
> On Sun, Jul 21, 2019 at 3:56 PM Luke Kenneth Casson Leighton
> <lkcl at lkcl.net> wrote:
> >
> > forgot to add an FPNumBaseRecord (the result). z will be used (back
> > in FPDivStage0Mod) to carry the sign and exponent right the way
> > through the DivPipe* pipeline. not DivPipeCore* pipeline classes,
> > because those handle the *mantissa*. DivPipeBaseData, by having an
> > FPNumBaseRecord, carries the sign and exponent (and the member
> > variable "m" gets ignored).
> >
> > it's... okay. z.m, by never being used, should get optimised out.
> >
> > @@ -28,6 +28,9 @@ class DivPipeConfig:
> > class DivPipeBaseData:
> > """ input data base type for ``DivPipe``.
> >
> > + :attribute z: a convenient way to carry the sign and exponent through
> > + the pipeline from when they were computed right at the
> > + start.
> > :attribute out_do_z: FIXME: document
> > :attribute oz: FIXME: document
> > :attribute ctx: FIXME: document
> > @@ -41,6 +44,7 @@ class DivPipeBaseData:
> > """ Create a ``DivPipeBaseData`` instance. """
> > self.config = config
> > width = config.pspec.width
> > + self.z = FPNumBaseRecord(width, False) # s and e carried: m ignored
> > self.out_do_z = Signal(reset_less=True)
> > self.oz = Signal(width, reset_less=True)
More information about the libre-riscv-dev
mailing list