発展編①:データ構造をクラス化して綺麗にまとめる

Parser

〜Timing Report解析をオブジェクト指向で整理する〜

📝 はじめに

これまでの記事では、

  • SlackやStartpoint/Endpointの抽出
  • CSV出力による一覧化

を行ってきました。
しかしコードが少し複雑になり、「どこで何を扱っているのか分かりにくい」 と感じた方もいると思います。

そこで今回は、Pythonの クラス(class) を使ってデータ構造を整理し、
Timing Report解析を「見通しの良いコード」に進化させます。


🎯 やりたいこと

  • 1つのパス(Startpoint, Endpoint, Slack)を「オブジェクト」として表現
  • リストにまとめて複数パスを扱えるようにする
  • コードの可読性・拡張性を高める

✍️ dataclassを使った例

Python 3.7以降では、dataclass を使うとシンプルにクラスを定義できます。

from dataclasses import dataclass

@dataclass
class TimingPath:
startpoint: str
endpoint: str
slack: float

これで、Timing Reportの1パスを表す「箱」ができました。

🔧 実際に使ってみる

前回の抽出結果(Startpoint / Endpoint / Slack)を、このクラスに格納してみましょう。

import re
from dataclasses import dataclass

@dataclass
class TimingPath:
    startpoint: str
    endpoint: str
    slack: float

filename = "timing_sample.rpt"

with open(filename, "r", encoding="utf-8") as f:
    text = f.read()

# 正規表現で抽出
start_pattern = r"Startpoint:\s*(.+)"
end_pattern   = r"Endpoint:\s*(.+)"
slack_pattern = r"slack.*?([-+]?\d*\.?\d+)"

start_matches = re.findall(start_pattern, text)
end_matches   = re.findall(end_pattern, text)
slack_matches = re.findall(slack_pattern, text, flags=re.IGNORECASE)

# クラスのリストに格納
paths = []
for sp, ep, sl in zip(start_matches, end_matches, slack_matches):
    path = TimingPath(startpoint=sp, endpoint=ep, slack=float(sl))
    paths.append(path)

# 出力
for p in paths:
    print(p)

出力例:

TimingPath(startpoint='U1/clk (rising edge-triggered flip-flop clocked by CLK)', endpoint='U5/data (rising edge-triggered flip-flop clocked by CLK)', slack=0.11)

📦 クラス化のメリット

  1. データがまとまる
    • paths[0].slack のようにアクセスできるので分かりやすい
  2. 拡張しやすい
    • 例えば arrival time, required time などのフィールドを追加するだけでOK
  3. コードの見通しが良い
    • dictやリストの入れ子よりも直感的

💡 応用ポイント

  • クラスに「メソッド」を追加して、自動でSlack判定(NG or OK)を返すようにできる
  • JSONに変換して保存することも簡単(dataclasses.asdict()を利用)
  • pandasと組み合わせれば、すぐに表形式で扱える

✅ まとめ

  • dataclassを使ってTiming Reportの1パスを「オブジェクト化」した
  • コードの可読性・拡張性が大幅にアップした
  • 今後の解析(pandasや可視化)にスムーズにつなげられる
タイトルとURLをコピーしました