Bug 311 - countzero function for Logic Pipeline
Summary: countzero function for Logic Pipeline
Status: RESOLVED FIXED
Alias: None
Product: Libre-SOC's first SoC
Classification: Unclassified
Component: Source Code (show other bugs)
Version: unspecified
Hardware: PC Mac OS
: --- enhancement
Assignee: Tobias Platen
URL:
Depends on: 312
Blocks:
  Show dependency treegraph
 
Reported: 2020-05-15 12:30 BST by Luke Kenneth Casson Leighton
Modified: 2020-06-30 16:54 BST (History)
1 user (show)

See Also:
NLnet milestone: ---
total budget (EUR) for completion of task and all subtasks: 0
budget (EUR) for this task, excluding subtasks' budget: 0
parent task for budget allocation:
child tasks for budget allocation:
The table of payments (in EUR) for this task; TOML format:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Comment 1 Luke Kenneth Casson Leighton 2020-05-15 12:34:29 BST
hm i don't think the count_right functionality is working correctly.  it
appears to count from the left up to the last 1, i.e. it returns
(64-countleftzeros)

this is count leading zeros:

* cntlzd.  RA,RS (Rc=1)

    n <- 0
    do while n < 64
      if (RS)[n]  = 1 then
         leave
      n <- n + 1
    RA <- n

and this is count trailing zeros:

* cnttzd.  RA,RS (Rc=1)

    n  <- 0
    do while n < 64
       if (RS)[63-n] = 0b1 then
            leave
       n  <- n + 1
    RA <- EXTZ64(n)

i am inclined to suggest that the entire input be inverted via a mux and
that encoder *not* try to do inversion.
Comment 2 Luke Kenneth Casson Leighton 2020-05-15 12:43:58 BST
i *think* this fixes it:

--- a/src/soc/countzero/countzero.py
+++ b/src/soc/countzero/countzero.py
@@ -53,14 +53,14 @@ class ZeroCounter(Elaboratable):
                 with m.Else():
                     m.d.comb += ret.eq(3)
             with m.Else():
-                with m.If(v[0]):
-                    m.d.comb += ret.eq(0)
-                with m.Elif(v[1]):
-                    m.d.comb += ret.eq(1)
+                with m.If(v[3]):
+                    m.d.comb += ret.eq(3)
                 with m.Elif(v[2]):
                     m.d.comb += ret.eq(2)
+                with m.Elif(v[1]):
+                    m.d.comb += ret.eq(1)
                 with m.Else():
-                    m.d.comb += ret.eq(3)
+                    m.d.comb += ret.eq(0)
             return ret
 
         r = IntermediateResult()
Comment 3 Luke Kenneth Casson Leighton 2020-05-15 14:18:05 BST
tobias i added this in:

https://git.libre-soc.org/?p=soc.git;a=blob;f=src/soc/logical/main_stage.py;h=76be8a6404b1648de20f10dc8a933b6c586d5a1c;hb=HEAD

next i'll put in a unit test into logical/test_pipe_caller.py
Comment 4 Luke Kenneth Casson Leighton 2020-05-15 14:51:27 BST
*face-palm*

i just realised that countzero is basically a PriorityEncoder
https://github.com/m-labs/nmigen/blob/master/nmigen/lib/coding.py

and that 90% of countzero.py can disappear as a result (sigh)

however it is not *just* a PriorityEncoder: countzero not only
changes the end from which it counts (MSB instead of LSB), it
changes 32-bit and 64-bit modes as well.

i am inclined however to suggest leaving that for now: what this
does mean however is that the formal proof is one that revolves
around PriorityEncoder more than anything else.

i will raise a suitable bugreport for that, now.