neoh 0.1.1

A declarative HDL transpiler for rapid testbench development.
WHITESPACE = _{ " " | "\t" | "\n" | "\r" }
COMMENT    = _{ "//" ~ (!"\n" ~ ANY)* }

identifier = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_")* }
integer    = @{ ASCII_DIGIT+ }
bits       = @{ integer ~ ":" ~ integer }

width_constraint = { "[" ~ "always" ~ bits ~ "]" }
expr             = { (identifier | integer) ~ (("+" | "-" | "*" | "/") ~ (identifier | integer))* }

// Rules referenced in verif_cmd
write_cmd = { "write" ~ identifier ~ "=" ~ expr ~ ";" }
put_stmt  = { "put" ~ identifier ~ ("=" | "+=" | "-=") ~ expr ~ width_constraint? ~ ";" }
expect_cmd = { "/" ~ integer ~ "expect" ~ "(" ~ expr ~ "==" ~ expr ~ ")" ~ ";" }
pulse_cmd  = { "pulse" ~ "len" ~ "(" ~ identifier ~ ")" ~ "," ~ "gap" ~ "(" ~ identifier ~ ")" ~ ";" }
watch_cmd = { "/" ~ integer ~ "watchfor" ~ expr ~ "<=" ~ expr ~ "&" ~ "/" ~ integer ~ "out" ~ "(" ~ out_arg ~ ")" ~ ";" }

verif_cmd = { expect_cmd | pulse_cmd | watch_cmd | write_cmd | put_stmt }

out_arg = { string_literal | identifier }
string_literal = @{ "\"" ~ (!"\"" ~ ANY)* ~ "\"" }

known_stmt = { "known" ~ identifier ~ "<=" ~ identifier ~ ("," ~ identifier)* ~ ";" }
ret_stmt = { "ret" ~ "tempassign" ~ identifier ~ width_constraint? ~ "<=" ~ expr ~ ";" }
pass_stmt = { identifier ~ "passparams" ~ identifier ~ "(" ~ params ~ ")" ~ ";" }
ret_var_stmt = { "ret" ~ identifier ~ ";" }
params = { identifier ~ ("," ~ identifier)* }

piece_def = { "piece" ~ identifier ~ "{" ~ piece_member ~ ("," ~ piece_member)* ~ "}" }
piece_member = { ("in" | "out") ~ identifier }

block_def = { ("pieced")? ~ "block" ~ identifier ~ "(" ~ block_params ~ ")" ~ ("logic")? ~ "{" ~ (ret_stmt | pass_stmt | ret_var_stmt | block_def)* ~ "}" }
block_params = { (identifier | piece_inst_param) ~ ("," ~ (identifier | piece_inst_param))* }
piece_inst_param = { identifier ~ "<=" ~ identifier }

testbench = { "testbench" ~ identifier ~ "(" ~ identifier ~ ")" ~ "{" ~ getvars_cmd ~ "when" ~ "(" ~ "BEGIN" ~ ")" ~ "{" ~ (verif_cmd)* ~ "}" ~ "}" }
getvars_cmd = { "getvars" ~ "(" ~ getvars_arg ~ ("," ~ getvars_arg)* ~ ")" ~ ";" }
getvars_arg = { ("!"? ~ identifier) | "*" }

testgroup = { "testgroup" ~ identifier ~ "{" ~ (do_stmt | same_block)* ~ "}" }
do_stmt = { "do" ~ identifier ~ ";" }
same_block = { "same" ~ "{" ~ (run_stmt)* ~ "}" }
run_stmt = { "run" ~ identifier ~ ";" }

file = { SOI ~ (known_stmt | block_def | piece_def | testbench | testgroup)* ~ EOI }