import gradio as gr q = 0 q_bar = 1 history = [] def sr_latch(s, r): global q, q_bar, history s = int(s) r = int(r) if s == 1 and r == 1: state = "INVALID" elif s == 1 and r == 0: q, q_bar = 1, 0 state = "SET" elif s == 0 and r == 1: q, q_bar = 0, 1 state = "RESET" else: state = "HOLD" q_display = "X" if state == "INVALID" else str(q) q_bar_display = "X" if state == "INVALID" else str(q_bar) history.append(f"S={s}, R={r} => Q={q_display}, Q'={q_bar_display} [{state}]") log = "\n".join(history) return q_display, q_bar_display, state, log def reset_latch(): global q, q_bar, history q = 0 q_bar = 1 history = [] return "0", "1", "HOLD", "" custom_css = """ .gradio-container { max-width: 720px !important; margin: auto; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } h1 { color: #1a1a2e !important; font-size: 28px !important; font-weight: 700 !important; margin-bottom: 4px !important; } .subtitle { color: #5a5a6e !important; font-size: 15px !important; } .output-box textarea { font-size: 22px !important; font-weight: 600 !important; text-align: center !important; color: #1a1a2e !important; } .history-box textarea { font-family: "SF Mono", "Fira Code", "Consolas", monospace !important; font-size: 13px !important; color: #3a3a4e !important; } .truth-table-wrap table { font-size: 14px !important; } .truth-table-wrap th { color: #5a5a6e !important; font-weight: 600 !important; } .truth-table-wrap td { color: #1a1a2e !important; } button.primary { background: #1a1a2e !important; color: #ffffff !important; border: none !important; } button.primary:hover { background: #2a2a3e !important; } input[type="radio"]:checked { accent-color: #1a1a2e !important; } """ with gr.Blocks(title="SR Latch Simulator") as demo: gr.Markdown("# SR Latch Simulator") gr.Markdown( "Toggle the S (set) and R (reset) inputs and click Apply to observe the latch behavior.", elem_classes=["subtitle"], ) with gr.Row(): s_input = gr.Radio(choices=["0", "1"], value="0", label="S (Set)") r_input = gr.Radio(choices=["0", "1"], value="0", label="R (Reset)") with gr.Row(): apply_btn = gr.Button("Apply", variant="primary") reset_btn = gr.Button("Reset") with gr.Row(): q_output = gr.Textbox(label="Q", value="0", interactive=False, elem_classes=["output-box"]) q_bar_output = gr.Textbox(label="Q'", value="1", interactive=False, elem_classes=["output-box"]) state_output = gr.Textbox(label="State", value="HOLD", interactive=False, elem_classes=["output-box"]) gr.Markdown("### Truth Table") gr.Dataframe( value=[ ["0", "0", "Prev", "Prev", "Hold"], ["1", "0", "1", "0", "Set"], ["0", "1", "0", "1", "Reset"], ["1", "1", "X", "X", "Invalid"], ], headers=["S", "R", "Q", "Q'", "State"], interactive=False, elem_classes=["truth-table-wrap"], ) gr.Markdown("### History") history_box = gr.Textbox( label="Log", lines=6, interactive=False, elem_classes=["history-box"], ) apply_btn.click( fn=sr_latch, inputs=[s_input, r_input], outputs=[q_output, q_bar_output, state_output, history_box], ) reset_btn.click( fn=reset_latch, inputs=[], outputs=[q_output, q_bar_output, state_output, history_box], ) if __name__ == "__main__": demo.launch(css=custom_css, theme=gr.themes.Base())