示例#1
0
 def expand(self):
     if self.logic_ is None:
         if self.name is None:
             raise ValueError(helper.error('An Fsm must be named', self))
         self.oprefix = "SM_" + self.name.upper() + "_"
         if self.behav:  # non synthesizable, if need to debug generation
             rstLst = (x <= x.default for x in self.body.assigned())
             rstLst = sorted(rstLst, key=lambda x: x.lhs.name)
             loopName = f"_loop"
             clocked = chipo.Clocked(self.clock,
                                     self.reset,
                                     name=f"{self.name}_clocked")
             clocked += \
                 chipo.Block(
                     chipo.If(self.reset.offExpr())[
                         chipo.Block(
                             chipo.While(1)[
                                 tuple(self.body.stmts),
                                 ...
                             ], name=loopName)
                     ],
                     *rstLst,
                     ...,
                 )
             clocked.hasWfe = True
             clocked.autoReset = False
             self.logic_ = clocked
         else:  # synthesizable output
             self.body = chipo.Block(
                 chipo.While(1).Do(..., *self.body.stmts))
             self.root = self.toDAG()
             self.mergeStates(self.root)
             self.logic_ = self.dumpTree(self.root)
     return self.logic_
示例#2
0
    def dumpSubtreeFsm(self, node: Node, mode: str, stateNode: Node,
                       visitedIn):
        visited = set(visitedIn)  # make a value copy
        out = chipo.Block()
        while node:
            if node.uid in visited:
                import sys
                visitedStr = ', '.join([str(x) for x in visited])
                print(showFromNode(self.root), file=sys.stderr)
                raise ValueError(
                    f"SM There is a loop path without clock-edges/... on " +
                    f"the set of nodes {visitedStr}. Currently @{node.uid}")

            bt, bf, nx = node.bt, node.bf, node.nx
            if node.typ == NodeType.stm:
                visited.add(node.uid)
                out += node.code
                node = node.succ()
            elif node.typ == NodeType.wfe:
                if mode == "rel" and node == stateNode:
                    out += chipo.Comment("stay")
                else:
                    out += chipo.SigAssign(self.state, self.stateName(node)) \
                           if self.sigFsm else \
                           chipo.VarAssign(self.state, self.stateName(node))
                node = None
            elif node.typ == NodeType.ife:
                visited.add(node.uid)
                cond = node.code
                if isIntVal(cond, 1):
                    blk = self.dumpSubtreeFsm(bt, mode, stateNode, visited)
                    chipo.appendStms(out, blk.asList())
                elif isIntVal(cond, 0):
                    n = bf or nx
                    if n:
                        blk = self.dumpSubtreeFsm(n, mode, stateNode, visited)
                        chipo.appendStms(out, blk.asList())
                else:
                    ife = chipo.If(cond)[self.dumpSubtreeFsm(
                        bt, mode, stateNode, visited)]
                    n = bf or nx
                    if n:
                        ife = ife.Else[self.dumpSubtreeFsm(
                            n, mode, stateNode, visited)]
                    out += ife
                node = None
            else:
                out += chipo.Comment(f"// Ignoring node={node} " +
                                     f"typ={node.typ} code='{node.code}'")
                node = node.succ()
        return out
示例#3
0
 def __init__(self, clock, reset, *, keep, name=None, vld=None, rdy=None):
     varname.Named.__init__(self, name)
     self.clock, self.reset = clock, reset
     self.keep = list(keep)
     self.body = chipo.Block()
     self.vld_up = vld
     self.rdy_dn = rdy
     self.vld = chipo.Signal(1, name='vld') if vld else None
     self.rdy = chipo.Signal(1, name='rdy') if rdy else None
     if rdy and not vld:
         raise ValueError(
             helper.error("If rdy provided, vld must be provided too",
                          self))
     self.logic_ = None
     self.outs_ = None
示例#4
0
 def __init__(self,
              clock=None,
              reset=None,
              *,
              name=None,
              behav=False,
              sigFsm=True,
              keep=[]):
     varname.Named.__init__(self, name)
     self.clock, self.reset = clock, reset
     self.keep = list(keep)
     self.body = chipo.Block()
     self.logic_ = None
     self.Q = "_q"
     self.wfeCounter = 0
     self.behav = behav
     self.sigFsm = sigFsm
     if sigFsm:  # dummy state name for mergeStates
         self.state = chipo.Signal(1, name='__theState__')
     else:
         self.state = chipo.Var(1, name='__theState__')
示例#5
0
    def dumpTree(self, root: Node):
        # create dict that links wfe nodes with its id
        wfeLst = [n for n in Node.all if n.typ == NodeType.wfe]
        wfeCnt = len(wfeLst)
        wfes = {}
        for node in wfeLst:
            wfeCnt -= 1
            node.code = wfeCnt
            wfes[node.code] = node

        # give unique names to the estates based on wfe nodes
        stateNames = [self.stateName(wfes[code]) for code in sorted(wfes)]

        # create state type
        States = chipo.Enu(*stateNames,
                           name=self.name + f"{self.name}_state_t")

        # find initial state
        initStateName = self.stateName(self.findFirstWfe(root))

        if self.sigFsm:
            self.state = chipo.Signal(States,
                                      name=f'{self.name}_state',
                                      default=initStateName)
        else:
            self.state = chipo.Var(States,
                                   name=f'{self.name}_state',
                                   default=initStateName)

        # start building the logic
        clocked = chipo.Clocked(self.clock,
                                self.reset,
                                name=f"{self.name}_clocked")

        # create transition switch statement
        switch = chipo.Switch(self.state)
        for code in sorted(wfes):
            node = wfes[code]
            stName = self.stateName(node)
            switch = switch.Case(stName)[self.dumpSubtreeFsm(node.succ(),
                                                             "rel",
                                                             node,
                                                             visitedIn=set())]

        if self.sigFsm:
            clocked += switch
            return clocked
        else:
            # create state signal
            stateQ = chipo.Signal(States,
                                  name=f'{self.name}_state' + self.Q,
                                  default=initStateName)
            combo = chipo.Combo(name=f"{self.name}_combo")
            # set next state variables to right default (flop output)
            sigs = {
                chipo.Signal(v, name=v.name + self.Q): v
                for v in chipo.sortedAsList(self.varAssigned())
            }
            sigs[stateQ] = self.state
            for s, v in sigs.items():
                clocked += chipo.SigAssign(s, v)
                combo += chipo.VarAssign(v, s)
            combo += switch
            return chipo.Block(combo, clocked)