def hardcodeRomIntoProcess(cls, rom): """ Due to verilog restrictions it is not posible to use array constants and rom memories has to be hardcoded as process """ processes = [] signals = [] for e in rom.endpoints: assert isinstance(e, Operator) and e.operator == AllOps.INDEX, e me, index = e.operands assert me is rom # construct output of the rom romValSig = rom.ctx.sig(rom.name, dtype=e.result._dtype) romValSig.hidden = False signals.append(romValSig) # construct process which will represent content of the rom cases = [(toHVal(i), [romValSig(v), ]) for i, v in enumerate(rom.def_val.val)] romSwitchStm = SwitchContainer(index, cases) for (_, (stm,)) in cases: stm.parentStm = romSwitchStm p = HWProcess(rom.name, [romSwitchStm, ], {index, }, {index, }, {romValSig, }) processes.append(p) # override usage of original index operator on rom # to use signal generated from this process for _e in e.result.endpoints: _e._replace_input(e.result, romValSig) rom.hidden = True return processes, signals
def HWProcess(cls, proc: HWProcess, ctx): """ Serialize HWProcess objects """ body = proc.statements extraVars = [] extraVarsSerialized = [] anyIsEventDependnt = arr_any( proc.sensitivityList, lambda s: isinstance(s, Operator)) sensitivityList = sorted( map(lambda s: cls.sensitivityListItem(s, ctx, anyIsEventDependnt), proc.sensitivityList)) hasToBeProcess = arr_any( proc.outputs, lambda x: verilogTypeOfSig(x) == SIGNAL_TYPE.REG ) if hasToBeProcess: childCtx = ctx.withIndent() else: childCtx = ctx def createTmpVarFn(suggestedName, dtype): s = RtlSignal(None, None, dtype, virtual_only=True) s.name = childCtx.scope.checkedName(suggestedName, s) s.hidden = False serializedS = cls.SignalItem(s, childCtx, declaration=True) extraVars.append(s) extraVarsSerialized.append(serializedS) return s childCtx.createTmpVarFn = createTmpVarFn statemets = [cls.asHdl(s, childCtx) for s in body] if hasToBeProcess: proc.name = ctx.scope.checkedName(proc.name, proc) extraVarsInit = [] for s in extraVars: a = Assignment(s.def_val, s, virtual_only=True) extraVarsInit.append(cls.Assignment(a, childCtx)) return cls.processTmpl.render( indent=getIndent(ctx.indent), name=proc.name, hasToBeProcess=hasToBeProcess, extraVars=extraVarsSerialized, sensitivityList=" or ".join(sensitivityList), statements=extraVarsInit + statemets )
def HWProcess(cls, proc: HWProcess, ctx: HwtSerializerCtx): body = proc.statements assert body proc.name = ctx.scope.checkedName(proc.name, proc) sensitivityList = sorted( map(cls.sensitivityListItem, proc.sensitivityList)) _body = "\n".join([cls.stmAsHdl(stm, ctx) for stm in body]) return processTmpl.render(indent=getIndent(ctx.indent), name=proc.name, sensitivityList=sensitivityList, stmLines=[_body])
def hardcodeRomIntoProcess(cls, rom): """ Due to verilog restrictions it is not posible to use array constants and rom memories has to be hardcoded as process """ processes = [] signals = [] for e in rom.endpoints: assert isinstance(e, Operator) and e.operator == AllOps.INDEX, e me, index = e.operands assert me is rom # construct output of the rom romValSig = rom.ctx.sig(rom.name, dtype=e.result._dtype) signals.append(romValSig) romValSig.hidden = False # construct process which will represent content of the rom cases = [(toHVal(i), [ romValSig(v), ]) for i, v in enumerate(rom.defVal.val)] statements = [ SwitchContainer(index, cases), ] for (_, (stm, )) in cases: stm.parentStm = statements[0] p = HWProcess(rom.name, statements, { index, }, { index, }, { romValSig, }) processes.append(p) # override usage of original index operator on rom # to use signal generated from this process def replaceOrigRomIndexExpr(x): if x is e.result: return romValSig else: return x for _e in e.result.endpoints: _e.operands = tuple(map(replaceOrigRomIndexExpr, _e.operands)) e.result = romValSig return processes, signals
def HWProcess(cls, proc: HWProcess, ctx: SerializerCtx): body = proc.statements assert body proc.name = ctx.scope.checkedName(proc.name, proc) sensitivityList = sorted( map(cls.sensitivityListItem, proc.sensitivityList)) childCtx = ctx.withIndent(2) _body = "\n".join([cls.stmAsHdl(stm, childCtx) for stm in body]) return processTmpl.render(hasConditions=arr_any( body, lambda stm: not isinstance(stm, Assignment)), name=proc.name, sensitivityList=sensitivityList, stmLines=[_body])
def tryToMerge(procA: HWProcess, procB: HWProcess): """ Try merge procB into procA :raise IncompatibleStructure: if merge is not possible :attention: procA is now result if merge has succeed :return: procA which is now result of merge """ if (checkIfIsTooSimple(procA) or checkIfIsTooSimple(procB) or areSetsIntersets(procA.outputs, procB.sensitivityList) or areSetsIntersets(procB.outputs, procA.sensitivityList) or not HdlStatement._is_mergable_statement_list( procA.statements, procB.statements)): raise IncompatibleStructure() procA.statements = HdlStatement._merge_statement_lists( procA.statements, procB.statements) procA.outputs.extend(procB.outputs) procA.inputs.extend(procB.inputs) procA.sensitivityList.extend(procB.sensitivityList) return procA
def _statements_to_HWProcesses(_statements, tryToSolveCombLoops)\ -> Generator[HWProcess, None, None]: assert _statements # try to simplify statements proc_statements = [] for _stm in _statements: stms, _ = _stm._try_reduce() proc_statements.extend(stms) outputs = UniqList() _inputs = UniqList() sensitivity = UniqList() enclosed_for = set() for _stm in proc_statements: seen = set() _stm._discover_sensitivity(seen) _stm._discover_enclosure() outputs.extend(_stm._outputs) _inputs.extend(_stm._inputs) sensitivity.extend(_stm._sensitivity) enclosed_for.update(_stm._enclosed_for) enclosure_values = {} for sig in outputs: # inject nopVal if needed if sig._useNopVal: n = sig._nopVal enclosure_values[sig] = n if enclosure_values: do_enclose_for = list(where(outputs, lambda o: o in enclosure_values)) fill_stm_list_with_enclosure(None, enclosed_for, proc_statements, do_enclose_for, enclosure_values) if proc_statements: for o in outputs: assert not o.hidden, o seen = set() inputs = UniqList() for i in _inputs: inputs.extend(i._walk_public_drivers(seen)) intersect = outputs.intersection_set(sensitivity) if intersect: if not tryToSolveCombLoops: raise HwtSyntaxError( "Combinational loop on signal(s)", intersect) # try to solve combinational loops by separating drivers of signals # from statements for sig in intersect: proc_statements, proc_stms_select = cut_off_drivers_of( sig, proc_statements) yield from _statements_to_HWProcesses(proc_stms_select, False) if proc_statements: yield from _statements_to_HWProcesses(proc_statements, False) else: name = name_for_process(outputs) yield HWProcess("assig_process_" + name, proc_statements, sensitivity, inputs, outputs) else: assert not outputs # this can happen e.g. when If does not contains any Assignment pass
def mkDriverProc(intf, tbCtx): d = HWProcess(intf._sigInside.name + "_driver", [], set(), set(), set()) d.actualTime = -1 d.driverFor = tbCtx[intf] return d