Skip to content

v0.15.1: SV構文拡張#16

Open
shadowlink0122 wants to merge 12 commits intomainfrom
feature/v0.15.1
Open

v0.15.1: SV構文拡張#16
shadowlink0122 wants to merge 12 commits intomainfrom
feature/v0.15.1

Conversation

@shadowlink0122
Copy link
Owner

v0.15.0のPR#14マージ以降の全変更をfeature/v0.15.1に移行:

  • SVバックエンド品質改善: 定数ビット幅推論・else if正規化・冗長除去
  • always_ff/always_comb/always_latch キーワード直接サポートと自動判別
  • SV構文拡張Phase1: bit[N]型・assign文・inoutサポート
  • SV構文拡張Phase2: enum→typedef enum・struct→struct packed・function→function automatic
  • SV連接({a,b})・複製({N{expr}})構文のフルパイプライン実装
  • 全60テストPASS

概要

変更点

関連Issue

テスト

  • 単体テスト追加/更新
  • 既存テスト通過
  • E2Eテスト確認(該当する場合)

チェックリスト

  • docker compose run --rm lint 通過
  • ドキュメント更新(必要な場合)
  • docs/design/ との整合性確認

v0.15.0のPR#14マージ以降の全変更をfeature/v0.15.1に移行:
- SVバックエンド品質改善: 定数ビット幅推論・else if正規化・冗長除去
- always_ff/always_comb/always_latch キーワード直接サポートと自動判別
- SV構文拡張Phase1: bit[N]型・assign文・inoutサポート
- SV構文拡張Phase2: enum→typedef enum・struct→struct packed・function→function automatic
- SV連接({a,b})・複製({N{expr}})構文のフルパイプライン実装
- 全60テストPASS
Copilot AI review requested due to automatic review settings March 10, 2026 15:14
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Cm の SystemVerilog バックエンド v0.15.1 として、SV 向けの構文・型・コード生成を拡張し、周辺ドキュメント/テスト/バージョン表記を更新する PR です。

Changes:

  • SV 向けに always(_ff/_comb/_latch)assignbit[N]inout{a,b}/{N{expr}} などの構文要素をフロントエンド〜MIR〜SV codegen へ伝搬
  • SV codegen の出力要素を拡充(localparam、typedef enum/struct packed、function/task、always_latch、concat/replicate など)
  • v0.15.1 ドキュメント追加とテスト追加、各種バージョンを 0.15.1 に更新

Reviewed changes

Copilot reviewed 99 out of 99 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
vscode-extension/package.json VSCode 拡張のバージョン更新 (0.15.1)
VERSION リポジトリのバージョン更新 (0.15.1)
src/main.cpp get_version() の既定値更新 (0.15.1)
src/frontend/lexer/token.hpp SV 用キーワード/トークン追加(always/assign/bit/initial 等)
src/frontend/lexer/token.cpp 追加トークンの文字列表現を追加
src/frontend/lexer/lexer.cpp SV キーワードテーブルに追加キーワードを登録
src/frontend/parser/parser_type.cpp bit 型のパース追加
src/frontend/parser/parser_stmt.cpp 型開始判定に bit を追加
src/frontend/parser/parser_decl.cpp always* 修飾子・assign トップレベル宣言・配列サフィックス先読み拡張
src/frontend/parser/parser_expr.cpp {...} を連接/複製/構造体リテラルとして判別するパース追加
src/frontend/ast/types.hpp AST TypeKind に Bit 追加
src/frontend/ast/decl.hpp FunctionDecl/GlobalVarDecl に always/assign フラグ追加
src/frontend/types/checking/call.cpp __builtin_concat / __builtin_replicate の型推論バイパス追加
src/hir/nodes.hpp HIR に always/assign フラグと属性を追加
src/hir/lowering/decl.cpp AST→HIR で always/assign/属性を伝搬
src/hir/lowering/expr.cpp __builtin_concat / __builtin_replicate を builtin として扱う
src/mir/nodes.hpp MIR に always/assign フラグ追加
src/mir/lowering/impl.cpp HIR→MIR で always kind を伝搬
src/mir/lowering/base.cpp const/assign の global var 登録挙動を変更
src/codegen/sv/codegen.hpp SVModule の出力要素(typedef/function/always_latch 等)を追加
src/codegen/sv/codegen.cpp SV の型/ビット幅/always 種別/assign/localparam/typedef/function/concat/replicate を実装
docs/v0.15.1/sv_syntax_reference.md v0.15.1 向け SV 構文リファレンス追加
docs/v0.15.1/sv_language_design.md v0.15.1 向け SV 言語デザイン文書追加
docs/v0.15.1/sv_extension_proposal.md SV 構文拡張提案文書追加
docs/v0.15.1/sv_cm_mapping.md Cm⇔SV マッピング表追加
tests/sv/basic/all_comparisons.cm SV 向け比較演算テスト追加
tests/sv/basic/all_comparisons.expect 期待結果追加
tests/sv/basic/all_operators.cm SV 向け演算子テスト追加
tests/sv/basic/all_operators.expect 期待結果追加
tests/sv/basic/assign_wire.cm SV assign テスト追加
tests/sv/basic/assign_wire.expect 期待結果追加
tests/sv/basic/bit_width.cm bit[N] テスト追加
tests/sv/basic/bit_width.expect 期待結果追加
tests/sv/basic/bool_logic.cm bool 論理演算テスト追加
tests/sv/basic/bool_logic.expect 期待結果追加
tests/sv/basic/increment.cm ++ 展開テスト追加
tests/sv/basic/increment.expect 期待結果追加
tests/sv/basic/inout_port.cm inout テスト追加
tests/sv/basic/inout_port.expect 期待結果追加
tests/sv/basic/internal_reg.cm 内部レジスタ宣言テスト追加
tests/sv/basic/internal_reg.expect 期待結果追加
tests/sv/basic/nested_ternary.cm 三項演算子ネストテスト追加
tests/sv/basic/nested_ternary.expect 期待結果追加
tests/sv/basic/signed_types.cm signed 型幅テスト追加
tests/sv/basic/signed_types.expect 期待結果追加
tests/sv/basic/unsigned_types.cm unsigned 型幅テスト追加
tests/sv/basic/unsigned_types.expect 期待結果追加
tests/sv/control/compound_conditions.cm 複合条件テスト追加
tests/sv/control/compound_conditions.expect 期待結果追加
tests/sv/control/deep_if_else.cm 深い if/else テスト追加
tests/sv/control/deep_if_else.expect 期待結果追加
tests/sv/control/for_loop.cm for ループテスト追加
tests/sv/control/for_loop.expect 期待結果追加
tests/sv/control/switch_case.cm switch/case テスト追加
tests/sv/control/switch_case.expect 期待結果追加
tests/sv/control/switch_fsm.cm switch + FSM テスト追加
tests/sv/control/switch_fsm.expect 期待結果追加
tests/sv/advanced/always_async_reset.cm 複数エッジ(非同期リセット)テスト追加
tests/sv/advanced/always_async_reset.expect 期待結果追加
tests/sv/advanced/always_auto_latch.cm always 自動ラッチ判別テスト追加
tests/sv/advanced/always_auto_latch.expect 期待結果追加
tests/sv/advanced/always_comb_explicit.cm always_comb 明示指定テスト追加
tests/sv/advanced/always_comb_explicit.expect 期待結果追加
tests/sv/advanced/always_comb_mux.cm always_comb(後方互換)テスト追加
tests/sv/advanced/always_comb_mux.expect 期待結果追加
tests/sv/advanced/always_counter.cm always_ff(後方互換)テスト追加
tests/sv/advanced/always_counter.expect 期待結果追加
tests/sv/advanced/always_ff_explicit.cm always_ff 明示指定テスト追加
tests/sv/advanced/always_ff_explicit.expect 期待結果追加
tests/sv/advanced/backward_compat_async.cm async 構文の後方互換テスト追加
tests/sv/advanced/backward_compat_async.expect 期待結果追加
tests/sv/advanced/backward_compat_comb.cm void(エッジなし) の後方互換テスト追加
tests/sv/advanced/backward_compat_comb.expect 期待結果追加
tests/sv/advanced/backward_compat_posedge.cm posedge 引数の後方互換テスト追加
tests/sv/advanced/backward_compat_posedge.expect 期待結果追加
tests/sv/advanced/clock_domain.cm clock_domain 属性テスト追加
tests/sv/advanced/clock_domain.expect 期待結果追加
tests/sv/advanced/concat_replicate.cm 連接/複製テスト追加
tests/sv/advanced/concat_replicate.expect 期待結果追加
tests/sv/advanced/const_expr.cm const 式→localparam テスト追加
tests/sv/advanced/const_expr.expect 期待結果追加
tests/sv/advanced/enum_typedef.cm enum→typedef enum テスト追加
tests/sv/advanced/enum_typedef.expect 期待結果追加
tests/sv/advanced/latch_explicit.cm always_latch 明示指定テスト追加
tests/sv/advanced/latch_explicit.expect 期待結果追加
tests/sv/advanced/localparam_const.cm const→localparam テスト追加
tests/sv/advanced/localparam_const.expect 期待結果追加
tests/sv/advanced/mixed_always.cm always_ff + always_comb 混在テスト追加
tests/sv/advanced/mixed_always.expect 期待結果追加
tests/sv/advanced/multi_always_comb.cm always_comb 複数ブロックテスト追加
tests/sv/advanced/multi_always_comb.expect 期待結果追加
tests/sv/advanced/struct_packed.cm struct→typedef struct packed テスト追加
tests/sv/advanced/struct_packed.expect 期待結果追加
tests/sv/advanced/sv_function.cm function automatic 出力テスト追加
tests/sv/advanced/sv_function.expect 期待結果追加
tests/sv/advanced/sv_param.cm parameter 出力テスト追加
tests/sv/advanced/sv_param.expect 期待結果追加
tests/sv/advanced/uart_counter.cm 複雑制御フロー+定数テスト追加
tests/sv/advanced/uart_counter.expect 期待結果追加
Comments suppressed due to low confidence (1)

src/mir/lowering/base.cpp:181

  • ここで return を削除して const 変数も mir_program.global_vars に登録するように変わっていますが、コメントの「非constグローバル変数のみMirGlobalVarとして登録」と矛盾しています。また、SV向けの意図であればターゲットに応じて挙動を切り替えないと LLVM など他バックエンドでも const がグローバル変数として出力されるようになり、従来挙動から変わります。意図を明確にした上でコメント更新・必要ならターゲット条件分岐を入れてください。
            // SVバックエンドではlocalparam出力のため、global_varsにも登録する
            // (returnせずフォールスルーで下のMirGlobalVar登録へ進む)
        }
    }

    // 非constグローバル変数のみMirGlobalVarとして登録
    auto mir_gv = std::make_unique<MirGlobalVar>();

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +567 to +572
std::ostringstream fn_ss;
indent_level_ = 1;

// 戻り値型を取得
bool is_void = true;
std::string ret_type_str = "void";
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

analyzeFunction() 内で indent_level_ を直接書き換えていますが(例: indent_level_ = 1)、この値は emitModule() の出力インデントにも使われるため、MIR解析後にモジュール全体が意図せずインデントされた状態で出力される可能性があります。解析中は現在の indent_level_ を保存して最後に必ず復元する(早期return含む)か、解析用のローカルインデント状態を別に持つようにしてください。

Suggested change
std::ostringstream fn_ss;
indent_level_ = 1;
// 戻り値型を取得
bool is_void = true;
std::string ret_type_str = "void";
struct IndentGuard {
int& level;
int saved;
explicit IndentGuard(int& l) : level(l), saved(l) {}
~IndentGuard() { level = saved; }
} indent_guard(indent_level_);
indent_level_ = 1;
std::ostringstream fn_ss;
// 戻り値型を取得
bool is_void = true;
std::string ret_type_str = "void";

Copilot uses AI. Check for mistakes.

### 3.3 `assign` (連続代入)

現時点では `assign` 文は属性ベースで生成されない。将来のサポート候補。
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このセクションで「assign 文は未サポート」となっていますが、このPRでは assign トークン/AST/HIR/MIR/codegen が追加されているため、現状の実装と矛盾します。現在の仕様(サポート有無・制約)に合わせて記述を更新してください。

Suggested change
現時点では `assign` 文は属性ベースで生成されない。将来のサポート候補
`assign` 文による連続代入はバックエンドでサポートされており、必要に応じて自動的に生成される。ただし、ユーザーコードから属性ベースで明示的に制御する仕組みは現時点では提供されていない

Copilot uses AI. Check for mistakes.
| `{N{expr}}` | `{N{expr}}` | 複製 (replication) |
| `x[7:0]` | `x[7:0]` | ビットスライス |
| `x[i]` | `x[i]` | ビット選択 |
| `!x` | `!x` | 論理否定 (1-bit) |
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここでは !x が SV の !x にマッピングされるとありますが、実装(SVCodeGen::emitRvalueMirUnaryOp::Not)は ~ を出力しています。どちらが正しい仕様かを決め、ドキュメントか実装のどちらかを合わせてください。

Suggested change
| `!x` | `!x` | 論理否定 (1-bit) |
| `!x` | `~x` | ビット反転 (1-bit) |

Copilot uses AI. Check for mistakes.
Comment on lines +1025 to +1028
// 空の {} はスキップ(ブロックとして扱う)
if (check(TokenKind::RBrace)) {
pos_ = saved_pos;
// 通常のブロック式として処理をフォールスルー
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{} (空の波括弧) を検出したときに pos_ を戻してフォールスルーしていますが、この関数内にブロック式(parse_block)の分岐が無いため、結果的に {} が一次式として消費されずパースエラーになります(以前は空の構造体リテラルとして解釈されていたはずです)。空ブロック式として扱いたいならここで parse_block() に委譲するか、空の連接/構造体リテラルとして明示的に処理してください。

Suggested change
// 空の {} はスキップ(ブロックとして扱う)
if (check(TokenKind::RBrace)) {
pos_ = saved_pos;
// 通常のブロック式として処理をフォールスルー
// 空の {} はブロック式として扱う
if (check(TokenKind::RBrace)) {
// ブロックパーサに委譲するため、位置を巻き戻す
pos_ = saved_pos;
return parse_block();

Copilot uses AI. Check for mistakes.
Comment on lines +112 to +121
for (size_t i = 0; i < call.args.size(); ++i) {
auto t = infer_type(*call.args[i]);
// __builtin_replicate: 2番目の引数(複製対象)の型を使用
// __builtin_concat: 最初の引数の型を使用
if (ident->name == "__builtin_replicate") {
if (i == 1) result_type = t; // 2番目の引数の型
} else {
if (!result_type) result_type = t;
}
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

__builtin_concat の戻り型を「最初の引数の型」に固定しているため、{a,b} のような連接でビット幅が変わるケース(例: bit[4] + bit[4] -> bit[8])でも型が更新されません。後段で型不整合を検出できなくなるので、少なくとも bit[N](Array)同士の連接は要素型が同じ前提でサイズを合算した配列型を返す、などの推論ロジックを入れてください。

Suggested change
for (size_t i = 0; i < call.args.size(); ++i) {
auto t = infer_type(*call.args[i]);
// __builtin_replicate: 2番目の引数(複製対象)の型を使用
// __builtin_concat: 最初の引数の型を使用
if (ident->name == "__builtin_replicate") {
if (i == 1) result_type = t; // 2番目の引数の型
} else {
if (!result_type) result_type = t;
}
}
// __builtin_concat 用の簡易幅推論:
// - 引数がすべて bit[N] (Array<Bit>) であれば、要素型を共有している前提で
// サイズ N を合算した配列型 bit[sum(N)] を返す。
// - それ以外の場合は従来通り「最初の引数の型」を返すフォールバック。
std::size_t concat_total_len = 0;
bool concat_all_bit_arrays = true;
ast::TypePtr concat_elem_type = nullptr;
auto update_concat_info = [&](const ast::TypePtr& t) {
// t が bit[N] (Array<Bit>) であれば concat_total_len / concat_elem_type を更新し、
// そうでなければ concat_all_bit_arrays を false にする。
// 型表現に依存しないよう dynamic_cast ベースの保守的なチェックを行う。
// プロジェクト側で ast::ArrayType / ast::BitType などの具象型を持っている前提。
struct ArrayTypeBase { virtual ~ArrayTypeBase() = default; };
struct BitTypeBase { virtual ~BitTypeBase() = default; };
auto* array_ty = dynamic_cast<ArrayTypeBase*>(t.get());
if (!array_ty) {
concat_all_bit_arrays = false;
return;
}
// 要素型とサイズにアクセスするために、実際の型に応じたキャストを行う。
// ここでは代表的なフィールド名 elem / element / element_type, length / size を想定しつつ、
// 利用可能なものだけを使う保守的な実装としている。
ast::TypePtr element_type = nullptr;
std::size_t length = 0;
// 想定: ArrayType 派生クラスに elem_type / element / element_type いずれかが存在
struct ArrayTypeWithElemAndLen : ArrayTypeBase {
ast::TypePtr elem;
std::size_t len;
};
if (auto* at = dynamic_cast<ArrayTypeWithElemAndLen*>(array_ty)) {
element_type = at->elem;
length = at->len;
} else {
// 要素型や長さが取得できない場合は保守的に諦める
concat_all_bit_arrays = false;
return;
}
if (!element_type) {
concat_all_bit_arrays = false;
return;
}
// 要素型が Bit であることを確認(名前ベースの保守的チェック)
bool is_bit_elem = false;
struct NamedTypeBase {
virtual ~NamedTypeBase() = default;
std::string name;
};
if (auto* nt = dynamic_cast<NamedTypeBase*>(element_type.get())) {
if (nt->name == "Bit" || nt->name == "bit") {
is_bit_elem = true;
}
}
if (!is_bit_elem || length == 0) {
concat_all_bit_arrays = false;
return;
}
if (!concat_elem_type) {
concat_elem_type = element_type;
} else {
// 要素型が食い違う場合も諦める
if (concat_elem_type.get() != element_type.get()) {
concat_all_bit_arrays = false;
return;
}
}
concat_total_len += length;
};
for (std::size_t i = 0; i < call.args.size(); ++i) {
auto t = infer_type(*call.args[i]);
// __builtin_replicate: 2番目の引数(複製対象)の型を使用
// __builtin_concat: 最初の引数の型を使用(フォールバック)
if (ident->name == "__builtin_replicate") {
if (i == 1) result_type = t; // 2番目の引数の型
} else {
if (!result_type) result_type = t;
// concat の場合は幅推論ロジックも試みる
update_concat_info(t);
}
}
if (ident->name == "__builtin_concat" &&
concat_all_bit_arrays &&
concat_elem_type &&
concat_total_len > 0) {
// bit[N] (Array<Bit>) 同士の連接と判定できた場合は、
// 要素型を維持したままサイズを合算した配列型を返す。
// ここでは ast::make_array のようなヘルパーが存在する前提で使用し、
// 存在しない場合はプロジェクト側で適宜置き換える必要がある。
extern ast::TypePtr make_array(const ast::TypePtr& elem, std::size_t len);
return make_array(concat_elem_type, concat_total_len);
}

Copilot uses AI. Check for mistakes.
Comment on lines +1645 to +1655
// count は整数リテラルなので、SV幅指定(32'd3等)を除去して素の数字にする
// "32'd3" → "3", "3" → "3"
auto pos_tick = count.find("'d");
if (pos_tick != std::string::npos) {
count = count.substr(pos_tick + 2);
} else {
pos_tick = count.find("'h");
if (pos_tick != std::string::npos) {
count = count.substr(pos_tick + 2);
}
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

複製 {N{expr}}count から幅指定を剥がす処理が "'d""'h" のみ対応で、"'sd""'b" 等が来ると意図通りに正規化されません。文字列パースに頼るより、count が整数定数ならその生値を使う/それ以外はそのまま出力する、などで安全に処理してください。

Suggested change
// count は整数リテラルなので、SV幅指定(32'd3等)を除去して素の数字にする
// "32'd3" → "3", "3" → "3"
auto pos_tick = count.find("'d");
if (pos_tick != std::string::npos) {
count = count.substr(pos_tick + 2);
} else {
pos_tick = count.find("'h");
if (pos_tick != std::string::npos) {
count = count.substr(pos_tick + 2);
}
}
// count は定数式として resolveArg が返した値をそのまま使用する

Copilot uses AI. Check for mistakes.
Comment on lines +195 to +203
### 6.3 カスタムビット幅 (新規)

```cm
// 任意ビット幅: bit<N> 構文
#[output] bit<4> nibble; // → output logic [3:0] nibble
#[output] bit<12> address; // → output logic [11:0] address

bit<26> counter; // → logic [25:0] counter
```
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この節では bit<4> のように山括弧で書く例になっていますが、実装側は bit を型として導入し、ビット幅は bit[4] のような配列サフィックス(角括弧)で表現する挙動になっています(parser_decl.cpp の配列サフィックススキップ等)。ドキュメントと実装の表記を統一してください。

Copilot uses AI. Check for mistakes.
Comment on lines +428 to +442
## 13. initial ブロック (シミュレーション専用)

```cm
initial {
clk = false;
rst = true;
// 10ns後にリセット解除
rst = false;
}
// → initial begin
// clk = 1'b0;
// rst = 1'b1;
// #10 rst = 1'b0;
// end
```
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initial 構文がサポートされている前提の記述になっていますが、現状の差分では lexer/token に KwInitial が追加されているだけで、パーサー(top-level/stmt)側に initial { ... } を受理する実装が見当たりません。実装を追加するか、未実装である旨(または将来対応)に修正してください。

Copilot uses AI. Check for mistakes.
Comment on lines +50 to +51
| `always @(posedge ... or negedge ...)` | 非同期リセット | 未サポート |
| `assign wire = expr;` | 連続代入 | 未サポート |
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この表では assignalways @(posedge ... or negedge ...)localparam などが「未サポート」となっていますが、このPRの実装では assign・非同期リセット(複数エッジ)・localparam 出力が追加されています。現状の実装に合わせて対応状況を更新してください。

Suggested change
| `always @(posedge ... or negedge ...)` | 非同期リセット | 未サポート |
| `assign wire = expr;` | 連続代入 | 未サポート |
| `always @(posedge ... or negedge ...)` | 非同期リセット | Cmトリガで複数エッジ指定時に `always_ff` を生成 |
| `assign wire = expr;` | 連続代入 | 一部の信号で `assign` を生成 |

Copilot uses AI. Check for mistakes.
| `KwPosedge` | `posedge` | `Posedge` | 立ち上がりエッジクロック |
| `KwNegedge` | `negedge` | `Negedge` | 立ち下がりエッジクロック |
| `KwWire` | `wire` | `Wire` | ワイヤ修飾型 |
| `KwReg` | `reg` | `Reg` | レジスタ修飾型 |
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SV固有トークン一覧が posedge/negedge/wire/reg のみになっていますが、このPRで always/always_ff/always_comb/always_latch/assign/initial/bit が追加されています(token.hpp)。ドキュメント側のトークン表も追加分を反映してください。

Suggested change
| `KwReg` | `reg` | `Reg` | レジスタ修飾型 |
| `KwReg` | `reg` | `Reg` | レジスタ修飾型 |
| `KwAlways` | `always` | `Always` | 一般的な always ブロック |
| `KwAlwaysFF` | `always_ff` | `AlwaysFF` | フリップフロップ用 always ブロック |
| `KwAlwaysComb` | `always_comb` | `AlwaysComb` | 組み合わせ回路用 always ブロック |
| `KwAlwaysLatch` | `always_latch` | `AlwaysLatch` | ラッチ用 always ブロック |
| `KwAssign` | `assign` | `Assign` | 連続代入文 |
| `KwInitial` | `initial` | `Initial` | 初期化/テストベンチ用 initial ブロック |
| `KwBit` | `bit` | `Bit` | 2値ビット型 |

Copilot uses AI. Check for mistakes.
- パーサー: extern struct 構文, フィールド属性パース (#[sv::param], #[output] 等)
- パーサー: extern struct フィールドのデフォルト値パース (= expr)
- パーサー: SVプラットフォームで初期値なし構造体型グローバル変数宣言を許可
- HIR/MIR: is_extern フラグ, フィールド属性, デフォルト値の伝播チェーン
- SV Codegen: extern struct typedef 出力抑制
- SV Codegen: モジュールインスタンス化文生成 (パラメータ + ポート接続)
- SV Codegen: extern struct 型のレジスタ宣言重複を解消
- テスト: extern_instance テストケース追加
- SVテスト 61/61 PASS, インタプリタテスト 349/372 PASS (既知18 FAIL)
v0.15.1のSV拡張(連接/複製構文)で暗黙的構造体リテラル {field: val, ...} のパースが
is_sv_platform_条件下に移動されたため、非SVテストで16件の回帰エラーが発生。
非SVプラットフォーム用の構造体リテラルパースを独立ブロックとして復元。

- インタプリタテスト: 349/372 → 365/372 PASS (16件修正)
- SVテスト: 61/61 PASS (回帰なし)
- 残り2 FAIL (generic_with_macro, typed_macro) はマクロ無限ループの既知問題
MIRToLLVM::convert のグローバル変数初期化で builder->CreateGlobalStringPtr を
使用していたが、IRBuilderにインサートポイント(BasicBlock)が設定されていない
状態での呼び出しがLLVM内部で無限ループを引き起こしていた。

修正: ConstantDataArray::getString + ConstantExpr::getInBoundsGetElementPtr で
IRBuilderを介さずにグローバル文字列定数を直接作成するよう変更。

- macro string テスト (typed_macro, generic_with_macro) の完全復旧
- インタプリタテスト: 367/372 PASS, 0 FAIL, 5 SKIP
- SVテスト: 61/61 PASS
MIR生成時に全関数の末尾に到達不能な 'return 0' ブロックが生成される。
LLVM O3最適化がこれを unreachable → ud2 (x86_64) に変換し、
Ubuntu環境でSIGILL (exit code 132)を引き起こしていた。

修正: convertFunctionにエントリブロックからのBFS到達可能性分析を追加。
Goto/SwitchInt/Callの遷移先を辿り到達可能ブロックを収集し、
到達不能ブロックのLLVMブロック作成とコード変換をスキップ。

- LLVM O3テスト: 403/411 PASS, 0 FAIL (Ubuntu x86_64 SIGILL解消)
- インタプリタテスト: 回帰なし
bytecodealliance/actions/wasmtime/setup@v1 がGitHub APIレート制限で
HTMLエラーページを受け取りCIが失敗する問題を修正。

Wasmtime公式インストールスクリプト(curl https://wasmtime.dev/install.sh)
による直接インストールに切り替え。
docs/v0.15.1/sv_tutorial.md: 包括的なSVバックエンドチュートリアル
- 構文・型マッピング・ポート宣言
- ロジックブロック (always_ff/always_comb) の4パターン
- 演算子マッピング・定数リテラル・ビット幅付与
- Cm独自の暗黙的変換 (代入方式自動決定・論理否定→ビット反転・
  clk/rst自動追加・MIR一時変数展開・else if正規化 等)
- SV属性一覧・トークン一覧・予約語
- LED点滅の完全な例 (Cm → SV 出力)
- docs/tutorials/en/compiler/sv.md: 英語版(v0.15.1対応詳細版に更新)
- docs/tutorials/ja/compiler/sv.md: 日本語版(v0.15.1対応詳細版に更新)
- docs/tutorials/en/index.md: SVバックエンドリンクを追加
- docs/tutorials/ja/index.md: SVバックエンドリンクを追加、進捗トラッカー更新
- docs/v0.15.1/sv_tutorial.md: 削除(正しい場所に移動)

内容: 暗黙的変換8項目、SV属性11項目、トークン一覧、
ロジックブロック4パターン、完全な例(Cm→SV出力)を網羅
コンパイラ (codegen/sv/codegen.cpp):
1. const → 常にlocalparam(#[sv::param]属性があってもconstなら変更不可)
   - 評価順序を反転: const チェックを #[sv::param] チェックより先に
   - #[sv::param] + 非const → parameter(外部からオーバーライド可能)
2. void/非void → task/function の自然マッピング
   - 引数あり(edge paramなし)の非void関数 → function automatic
   - 引数あり(edge paramなし)のvoid関数 → task automatic
   - 引数なしvoid関数 → always_comb (後方互換維持)
   - #[sv::function]/#[sv::task] 属性は不要に

ドキュメント:
- tutorials/en/compiler/sv.md: parameter/function/task の説明修正
- tutorials/ja/compiler/sv.md: 同上
- docs/v0.15.1/sv_language_design.md: #[sv::param] const → 非const に修正
- docs/v0.15.1/sv_syntax_reference.md: parameter属性の説明修正

テスト: SVテスト 61/61 PASS、回帰なし
コンパイラ (codegen/sv/codegen.cpp):
1. #[sv::param] → parameter のコードを完全削除
   - const は常に localparam に変換(属性不要)
   - parameter 宣言は生成しない
2. task 出力を完全削除
   - void関数は常に always_comb(引数あり/なし関わらず)
   - 非void関数(戻り値あり)のみ function automatic
   - task は合成に不適切なため廃止

テスト:
- parameterized.cm: #[sv::param] → const に変更
- SVテスト 61/61 PASS、回帰なし

ドキュメント:
- tutorials/en/ja/compiler/sv.md: #[sv::param]・task 記述削除
- v0.15.1/sv_syntax_reference.md: parameter行をlocalparam行に修正
- v0.15.1/sv_language_design.md: 既に前コミットで修正済み
コンパイラ (codegen/sv/codegen.cpp):
1. function内MIRテンポラリ変数のインライン展開
   - always ブロックと同じ2パス処理を function にも適用
   - _tXXXX 変数が除去されクリーンな出力に
2. 一般function呼び出しのSV出力を実装
   - result = func_name(arg1, arg2); として出力
   - always_comb/always_ff 内での関数呼び出しが可能に
3. else if 正規化後のインデント修正
   - 結合時にブロック内のインデントを4スペース浅く調整
   - 余分なend除去も統合した新ロジック

ドキュメント (tutorials/en,ja/compiler/sv.md):
4. 数値区切り文字の記述を削除(未サポート)
5. localparam出力例に型情報 logic [31:0] を追加

テスト: SVテスト 61/61 PASS、回帰なし
ドキュメント (tutorials/en,ja/compiler/sv.md):
- switch/case構文を正しい case(pattern) 形式に修正
  - 旧: case 0: { ... } / default: { ... }
  - 新: case(0) { ... } / else { ... }
- enum + switch FSMの使用例を追加
  - case(State::IDLE) { ... } 形式でenum マッチ

テスト: SVテスト 61/61 PASS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants