def lts_to_verilog(lts:LTS, module_name:str) -> str: s = StrAwareList() s += 'module {module}({inputs}, {outputs});'.format( inputs=', '.join(map(lambda sig: sig.name, lts.input_signals)), outputs=', '.join(map(lambda sig: sig.name, lts.output_signals)), module=module_name) s.newline() s += '\n'.join(['input {sig};'.format(sig=sig.name) for sig in lts.input_signals]) s.newline() s += '\n'.join(['output {sig};'.format(sig=sig.name) for sig in lts.output_signals]) s.newline() # TODO: don't use latches for state-less models nof_state_bits = math.ceil(math.log2(len(lts.states))) s += 'reg [{max_bit}:0] {state};'.format(max_bit=int(max(0., nof_state_bits-1)), # max_bit is at least 0 state=lts.state_name) s.newline() s += '\n'.join(['wire {out};'.format(out=sig.name) for sig in lts.output_signals]) s.newline() for out_sig, value_tuples in lts.output_models.items(): labels_true = lmap(lambda x: x[0], filter(lambda label_value: label_value[1], value_tuples.items())) assign = 'assign {sig} = {true_expr};'.format(sig=out_sig.name, true_expr=' || '.join(map(_label_to_verilog, labels_true)) if labels_true else '0') s += assign s.newline() s += 'initial begin' s += '{state} = 0;'.format(state=lts.state_name) s += 'end' s.newline() s += 'always@($global_clock)' s += 'begin' # you can also use '=' instead of '<=' here, but we will be strict tau_items = tuple(lts.tau_model.items()) s += 'if ({expr}) {state} <= {next_val};'.format(expr=_label_to_verilog(tau_items[0][0]), state=lts.state_name, next_val=tau_items[0][1]) for lbl, val in tau_items[1:]: s += 'else if ({expr}) {state} <= {next_val};'.format(expr=_label_to_verilog(lbl), state=lts.state_name, next_val=val) s += 'end' s += 'endmodule' return s.to_str()
def lts_to_verilog(lts:LTS) -> str: s = StrAwareList() s += 'module model(i_clk, \n{inputs}, \n{outputs});'.format(inputs=', '.join(map(lambda sig: sig.name, lts.input_signals)), outputs=', '.join(map(lambda sig: sig.name, lts.output_signals))) s.newline() s += 'input i_clk;' s += '\n'.join(['input {sig};'.format(sig=sig.name) for sig in lts.input_signals]) s.newline() s += '\n'.join(['output {sig};'.format(sig=sig.name) for sig in lts.output_signals]) s.newline() nof_state_bits = max(1, math.ceil(math.log2(len(lts.states)))) s += 'reg [{max_bit}:0] {state};'.format(max_bit=nof_state_bits-1, state=lts.state_name) s.newline() s += '\n'.join(['wire {out};'.format(out=sig.name) for sig in lts.output_signals]) s.newline() for out_sig, value_tuples in lts.output_models.items(): labels_true = lmap(lambda x: x[0], filter(lambda label_value: label_value[1], value_tuples.items())) assign = 'assign {sig} = {true_expr};'.format(sig=out_sig.name, true_expr=' || '.join(map(_label_to_verilog, labels_true)) if labels_true else '0') s += assign s.newline() s += 'initial begin' s += '{state} = 0;'.format(state=lts.state_name) s += 'end' s.newline() s += 'always@(posedge i_clk)' s += 'begin' tau_items = tuple(lts.tau_model.items()) s += 'if ({expr}) {state} = {next_val};'.format(expr=_label_to_verilog(tau_items[0][0]), state=lts.state_name, next_val=tau_items[0][1]) for lbl, val in tau_items[1:]: s += 'else if ({expr}) {state} = {next_val};'.format(expr=_label_to_verilog(lbl), state=lts.state_name, next_val=val) s += 'end' s += 'endmodule' return s.to_str()
def atm_to_verilog(atm: Automaton, sys_inputs: Iterable[Signal], sys_outputs: Iterable[Signal], module_name: str, bad_out_name: str) -> str: assert len(lfilter(lambda n: is_final_sink(n), atm.nodes)) == 1,\ 'for now I support only one bad state which must be a sink' sys_inputs = set(sys_inputs) sys_outputs = set(sys_outputs) verilog_by_sig = {s: 'controllable_' + s.name for s in sys_outputs} verilog_by_sig.update({s: s.name for s in sys_inputs}) verilog_by_node = {q: '__q' + q.name for q in atm.nodes} sink_q = lfilter(lambda n: is_final_sink(n), atm.nodes)[0] module_inputs = list( chain(map(lambda i: i.name, sys_inputs), map(lambda o: 'controllable_' + o.name, sys_outputs))) s = StrAwareList() s += 'module {module_name}({inputs}, {output});'.format( module_name=module_name, inputs=', '.join(module_inputs), output=bad_out_name) s.newline() s += '\n'.join('input %s;' % i for i in module_inputs) s.newline() s += 'output %s;' % bad_out_name s.newline() s += '\n'.join('reg %s;' % vq for vq in verilog_by_node.values()) s.newline() s += 'wire %s;' % bad_out_name s += 'assign {bad} = {sink_q};'.format(bad=bad_out_name, sink_q=verilog_by_node[sink_q]) s.newline() s += 'initial begin' s += '\n'.join('%s = 1;' % verilog_by_node[iq] for iq in atm.init_nodes) s += '\n'.join('%s = 0;' % verilog_by_node[q] for q in atm.nodes - atm.init_nodes) s += 'end' s.newline() s += 'always@($global_clock)' s += 'begin' def lbl_to_v(lbl: Label) -> str: return ' && '.join( ('!%s', '%s')[lbl[s]] % verilog_by_sig[s] for s in lbl) or '1' for q in atm.nodes: incoming_edges = incoming_transitions(q, atm) if not incoming_edges: update_expr = '0' else: update_expr = ' || '.join('{src} && {lbl}'.format( src=verilog_by_node[edge[0]], lbl=lbl_to_v(edge[1])) for edge in incoming_edges) s += ' {q} <= {update_expr};'.format(q=verilog_by_node[q], update_expr=update_expr) s += 'end' s += 'endmodule' return s.to_str()