james-kramer commited on
Commit
35cb0c1
·
verified ·
1 Parent(s): 95e33a5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +110 -113
app.py CHANGED
@@ -1,5 +1,5 @@
1
  import math
2
- import gradio
3
  import pandas
4
 
5
  from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
@@ -8,53 +8,51 @@ MODEL_ID = "HuggingFaceTB/SmolLM2-135M-Instruct"
8
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
9
  pipe = pipeline(
10
  task="text-generation",
11
- model=AutoModelForCausalLM.from_pretrained(
12
- MODEL_ID,
13
- ),
14
  tokenizer=tokenizer
15
  )
16
 
17
  def clock_calc(t_clock_to_q: float, t_logic, t_logic_min, t_setup, t_hold, t_skew):
18
-
19
- t_clock_min = t_clock_to_q + t_logic + t_setup + t_skew
20
- if t_clock_min > 0:
21
- f_max = 1.0 / (t_clock_min * 1e-9)
22
- else:
23
- f_max = math.inf
24
-
25
- setup_slack = 0.0
26
-
27
- hold_margin = t_clock_to_q + t_logic_min - t_skew - t_hold
28
- hold_met = hold_margin >= 0.0
29
-
30
- if t_hold > 0:
31
- hold_time = t_clock_to_q + t_logic_min - t_skew
32
- hold_safety = hold_time / t_hold
33
- else:
34
- hold_safety = math.inf
35
- timing_breakdown = {
36
- "t_clock_to_q": t_clock_to_q,
37
- "t_logic": t_logic,
38
- "t_setup": t_setup,
39
- "t_skew": t_skew,
40
- "total": t_clock_min
41
- }
42
-
43
- ok = hold_met
44
-
45
- if f_max >= 1e9:
46
- freq_display = f"{f_max/1e9:.3f} GHz"
47
- else:
48
- freq_display = f"{f_max/1e6:.2f} MHz"
49
-
50
- return dict(
51
  results={
52
  "f_max_hz": f_max,
53
  "f_max_mhz": f_max / 1e6,
54
  "f_max_ghz": f_max / 1e9,
55
- "t_clock_min_ns": t_clock_min,
56
- "setup_slack_ns": setup_slack,
57
- "hold_margin_ns": hold_margin,
58
  "hold_safety_factor": hold_safety,
59
  "freq_display": freq_display,
60
  },
@@ -78,61 +76,59 @@ def clock_calc(t_clock_to_q: float, t_logic, t_logic_min, t_setup, t_hold, t_ske
78
  },
79
  timing_breakdown=timing_breakdown,
80
  )
81
-
82
  def _format_chat(system_prompt: str, user_prompt: str) -> str:
83
- messages = [
84
- {"role": "system", "content": system_prompt},
85
- {"role": "user", "content": user_prompt},
86
- ]
87
- template = getattr(tokenizer, "chat_template", None)
88
- return tokenizer.apply_chat_template(
89
- messages,
90
- tokenize=False,
91
- add_generation_prompt=True
92
- )
93
 
94
  def _llm_generate(prompt: str, max_tokens: int) -> str:
95
- out = pipe(
96
- prompt,
97
- max_new_tokens=max_tokens,
98
- do_sample=True,
99
- temperature=0.5,
100
- return_full_text=False,
101
- )
102
- return out[0]["generated_text"]
103
 
104
  def llm_explain(results: dict, inputs: list) -> str:
 
 
 
 
 
 
 
 
 
105
 
106
- t_clock_to_q, t_logic, t_logic_min, t_setup, t_hold, t_skew = inputs
107
- r = results["results"]
108
- v = results["verdict"]
109
-
110
- system_prompt = (
111
- "You explain digital circuit timing to a smart highschooler. "
112
- "Use everyday analogies (like traffic lights, relay races) to support the explanation. "
113
- "You always return CONCISE responses, only one or two sentences."
114
- )
115
-
116
- user_prompt = (
117
- f"The digital circuit has a clock-to-Q delay of {t_clock_to_q:g} ns, "
118
- f"combinational logic delay of {t_logic:g} ns (max) and {t_logic_min:g} ns (min), "
119
- f"setup time of {t_setup:g} ns, hold time of {t_hold:g} ns, "
120
- f"and clock skew of {t_skew:g} ns.\n"
121
- f"The maximum operating frequency is {r['freq_display']}, "
122
- f"requiring a minimum clock period of {r['t_clock_min']:.2f} ns. "
123
- f"The hold timing has a margin of {r['hold_margin']:.3f} ns with "
124
- f"safety factor = {r['hold_safety_factor']:.2f}. "
125
- f"Setup constraint: {v['setup_message']}. "
126
- f"Hold constraint: {v['hold_message']}. "
127
- f"Overall: {v['recommendation']}. "
128
- "Explain what limits the clock speed and whether the design is safe in ONE to TWO friendly sentences for a non-expert."
129
- )
130
-
131
- format = _format_chat(system_prompt, user_prompt)
132
- return _llm_generate(format, max_tokens=128)
133
 
134
  def run_once(t_clock_to_q, t_logic, t_logic_min, t_setup, t_hold, t_skew):
135
- d = clock_calc(
136
  t_clock_to_q=float(t_clock_to_q),
137
  t_logic=float(t_logic),
138
  t_logic_min=float(t_logic_min),
@@ -140,8 +136,8 @@ def run_once(t_clock_to_q, t_logic, t_logic_min, t_setup, t_hold, t_skew):
140
  t_hold=float(t_hold),
141
  t_skew=float(t_skew)
142
  )
143
-
144
- df = pandas.DataFrame([{
145
  "Max Frequency": d["results"]["freq_display"],
146
  "Min Period [ns]": round(d["results"]["t_clock_min"], 3),
147
  "Setup Slack [ns]": round(d["results"]["setup_slack"], 3),
@@ -150,39 +146,40 @@ def run_once(t_clock_to_q, t_logic, t_logic_min, t_setup, t_hold, t_skew):
150
  "Setup Status": d["verdict"]["setup_message"],
151
  "Hold Status": d["verdict"]["hold_message"],
152
  }])
153
-
154
- narrative = llm_explain(d, inputs).split("\n")[0]
155
- return df, narrative
156
 
157
- with gradio.Blocks() as demo:
 
 
 
158
 
159
- gradio.Markdown(
160
- "# Run and Explain Digital Circuit Timing"
161
- )
162
- gradio.Markdown(
163
  "This app runs some simple calculations for a digital circuit and returns a natural language description of the results"
164
  )
165
 
166
- with gradio.Row():
167
- t_clock_to_q = gradio.Number(value=0.5, label="Clock-to-Q delay [ns]")
168
- t_setup = gradio.Number(value=0.4, label="Setup time [ns]")
169
- t_hold = gradio.Number(value=0.1, label="Hold time [ns]")
170
 
171
- with gradio.Row():
172
- t_logic = gradio.Number(value=8.0, label="Max logic delay [ns]")
173
- t_logic_min = gradio.Number(value=0.3, label="Min logic delay [ns]")
174
- t_skew = gradio.Number(value=0.5, label="Clock skew [ns]")
175
 
176
- # Add a button to click to run the interface
177
- run_btn = gradio.Button("Compute")
178
 
179
- results_df = gradio.Dataframe(label="Numerical results (deterministic)", interactive=False)
180
- explain_md = gradio.Markdown(label="Explanation")
181
 
182
- run_btn.click(fn=run_once, inputs=[t_clock_to_q, t_logic, t_logic_min, t_setup, t_hold, t_skew], outputs=[results_df, explain_md])
 
 
 
 
183
 
184
- # Finally, add a few examples
185
- gradio.Examples(
186
  examples=[
187
  [0.5, 8.0, 0.3, 0.4, 0.1, 0.5],
188
  [0.08, 0.4, 0.05, 0.06, 0.03, 0.02],
@@ -195,4 +192,4 @@ with gradio.Blocks() as demo:
195
  )
196
 
197
  if __name__ == "__main__":
198
- demo.launch(debug=True)
 
1
  import math
2
+ import gradio as gr
3
  import pandas
4
 
5
  from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
 
8
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
9
  pipe = pipeline(
10
  task="text-generation",
11
+ model=AutoModelForCausalLM.from_pretrained(MODEL_ID),
 
 
12
  tokenizer=tokenizer
13
  )
14
 
15
  def clock_calc(t_clock_to_q: float, t_logic, t_logic_min, t_setup, t_hold, t_skew):
16
+ t_clock_min = t_clock_to_q + t_logic + t_setup + t_skew
17
+ if t_clock_min > 0:
18
+ f_max = 1.0 / (t_clock_min * 1e-9)
19
+ else:
20
+ f_max = math.inf
21
+
22
+ setup_slack = 0.0
23
+
24
+ hold_margin = t_clock_to_q + t_logic_min - t_skew - t_hold
25
+ hold_met = hold_margin >= 0.0
26
+
27
+ if t_hold > 0:
28
+ hold_time = t_clock_to_q + t_logic_min - t_skew
29
+ hold_safety = hold_time / t_hold
30
+ else:
31
+ hold_safety = math.inf
32
+
33
+ timing_breakdown = {
34
+ "t_clock_to_q": t_clock_to_q,
35
+ "t_logic": t_logic,
36
+ "t_setup": t_setup,
37
+ "t_skew": t_skew,
38
+ "total": t_clock_min
39
+ }
40
+
41
+ ok = hold_met
42
+
43
+ if f_max >= 1e9:
44
+ freq_display = f"{f_max/1e9:.3f} GHz"
45
+ else:
46
+ freq_display = f"{f_max/1e6:.2f} MHz"
47
+
48
+ return dict(
49
  results={
50
  "f_max_hz": f_max,
51
  "f_max_mhz": f_max / 1e6,
52
  "f_max_ghz": f_max / 1e9,
53
+ "t_clock_min": t_clock_min,
54
+ "setup_slack": setup_slack,
55
+ "hold_margin": hold_margin,
56
  "hold_safety_factor": hold_safety,
57
  "freq_display": freq_display,
58
  },
 
76
  },
77
  timing_breakdown=timing_breakdown,
78
  )
79
+
80
  def _format_chat(system_prompt: str, user_prompt: str) -> str:
81
+ messages = [
82
+ {"role": "system", "content": system_prompt},
83
+ {"role": "user", "content": user_prompt},
84
+ ]
85
+ return tokenizer.apply_chat_template(
86
+ messages,
87
+ tokenize=False,
88
+ add_generation_prompt=True
89
+ )
 
90
 
91
  def _llm_generate(prompt: str, max_tokens: int) -> str:
92
+ out = pipe(
93
+ prompt,
94
+ max_new_tokens=max_tokens,
95
+ do_sample=True,
96
+ temperature=0.5,
97
+ return_full_text=False,
98
+ )
99
+ return out[0]["generated_text"]
100
 
101
  def llm_explain(results: dict, inputs: list) -> str:
102
+ t_clock_to_q, t_logic, t_logic_min, t_setup, t_hold, t_skew = inputs
103
+ r = results["results"]
104
+ v = results["verdict"]
105
+
106
+ system_prompt = (
107
+ "You explain digital circuit timing to a smart highschooler. "
108
+ "Use everyday analogies (like traffic lights, relay races) to support the explanation. "
109
+ "You always return CONCISE responses, only one or two sentences."
110
+ )
111
 
112
+ user_prompt = (
113
+ f"The digital circuit has a clock-to-Q delay of {t_clock_to_q:g} ns, "
114
+ f"combinational logic delay of {t_logic:g} ns (max) and {t_logic_min:g} ns (min), "
115
+ f"setup time of {t_setup:g} ns, hold time of {t_hold:g} ns, "
116
+ f"and clock skew of {t_skew:g} ns.\n"
117
+ f"The maximum operating frequency is {r['freq_display']}, "
118
+ f"requiring a minimum clock period of {r['t_clock_min']:.2f} ns. "
119
+ f"The hold timing has a margin of {r['hold_margin']:.3f} ns with "
120
+ f"safety factor = {r['hold_safety_factor']:.2f}. "
121
+ f"Setup constraint: {v['setup_message']}. "
122
+ f"Hold constraint: {v['hold_message']}. "
123
+ f"Overall: {v['recommendation']}. "
124
+ "Explain what limits the clock speed and whether the design is safe in ONE to TWO friendly sentences for a non-expert."
125
+ )
126
+
127
+ formatted = _format_chat(system_prompt, user_prompt)
128
+ return _llm_generate(formatted, max_tokens=128)
 
 
 
 
 
 
 
 
 
 
129
 
130
  def run_once(t_clock_to_q, t_logic, t_logic_min, t_setup, t_hold, t_skew):
131
+ d = clock_calc(
132
  t_clock_to_q=float(t_clock_to_q),
133
  t_logic=float(t_logic),
134
  t_logic_min=float(t_logic_min),
 
136
  t_hold=float(t_hold),
137
  t_skew=float(t_skew)
138
  )
139
+
140
+ df = pandas.DataFrame([{
141
  "Max Frequency": d["results"]["freq_display"],
142
  "Min Period [ns]": round(d["results"]["t_clock_min"], 3),
143
  "Setup Slack [ns]": round(d["results"]["setup_slack"], 3),
 
146
  "Setup Status": d["verdict"]["setup_message"],
147
  "Hold Status": d["verdict"]["hold_message"],
148
  }])
 
 
 
149
 
150
+ # fix: define inputs here
151
+ inputs = [t_clock_to_q, t_logic, t_logic_min, t_setup, t_hold, t_skew]
152
+ narrative = llm_explain(d, inputs).split("\n")[0]
153
+ return df, narrative
154
 
155
+ with gr.Blocks() as demo:
156
+ gr.Markdown("# Run and Explain Digital Circuit Timing")
157
+ gr.Markdown(
 
158
  "This app runs some simple calculations for a digital circuit and returns a natural language description of the results"
159
  )
160
 
161
+ with gr.Row():
162
+ t_clock_to_q = gr.Number(value=0.5, label="Clock-to-Q delay [ns]")
163
+ t_setup = gr.Number(value=0.4, label="Setup time [ns]")
164
+ t_hold = gr.Number(value=0.1, label="Hold time [ns]")
165
 
166
+ with gr.Row():
167
+ t_logic = gr.Number(value=8.0, label="Max logic delay [ns]")
168
+ t_logic_min = gr.Number(value=0.3, label="Min logic delay [ns]")
169
+ t_skew = gr.Number(value=0.5, label="Clock skew [ns]")
170
 
171
+ run_btn = gr.Button("Compute")
 
172
 
173
+ results_df = gr.Dataframe(label="Numerical results (deterministic)", interactive=False)
174
+ explain_md = gr.Markdown()
175
 
176
+ run_btn.click(
177
+ fn=run_once,
178
+ inputs=[t_clock_to_q, t_logic, t_logic_min, t_setup, t_hold, t_skew],
179
+ outputs=[results_df, explain_md]
180
+ )
181
 
182
+ gr.Examples(
 
183
  examples=[
184
  [0.5, 8.0, 0.3, 0.4, 0.1, 0.5],
185
  [0.08, 0.4, 0.05, 0.06, 0.03, 0.02],
 
192
  )
193
 
194
  if __name__ == "__main__":
195
+ demo.launch(debug=True)