verilog: save and restore overwritten macro arguments

This commit is contained in:
Zachary Snow 2021-07-15 10:36:50 -04:00 committed by Zachary Snow
parent a055145b95
commit 3156226233
4 changed files with 54 additions and 4 deletions

View File

@ -36,6 +36,7 @@
#include "verilog_frontend.h"
#include "kernel/log.h"
#include <assert.h>
#include <stack>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
@ -334,6 +335,11 @@ define_map_t::add(const std::string &name, const std::string &txt, const arg_map
defines[name] = std::unique_ptr<define_body_t>(new define_body_t(txt, args));
}
void define_map_t::add(const std::string &name, const define_body_t &body)
{
defines[name] = std::unique_ptr<define_body_t>(new define_body_t(body));
}
void define_map_t::merge(const define_map_t &map)
{
for (const auto &pr : map.defines) {
@ -440,7 +446,17 @@ static bool read_argument(std::string &dest)
}
}
static bool try_expand_macro(define_map_t &defines, std::string &tok)
using macro_arg_stack_t = std::stack<std::pair<std::string, define_body_t>>;
static void restore_macro_arg(define_map_t &defines, macro_arg_stack_t &macro_arg_stack)
{
log_assert(!macro_arg_stack.empty());
auto &overwritten_arg = macro_arg_stack.top();
defines.add(overwritten_arg.first, overwritten_arg.second);
macro_arg_stack.pop();
}
static bool try_expand_macro(define_map_t &defines, macro_arg_stack_t &macro_arg_stack, std::string &tok)
{
if (tok == "`\"") {
std::string literal("\"");
@ -450,7 +466,7 @@ static bool try_expand_macro(define_map_t &defines, std::string &tok)
if (ntok == "`\"") {
insert_input(literal+"\"");
return true;
} else if (!try_expand_macro(defines, ntok)) {
} else if (!try_expand_macro(defines, macro_arg_stack, ntok)) {
literal += ntok;
}
}
@ -495,6 +511,10 @@ static bool try_expand_macro(define_map_t &defines, std::string &tok)
args.push_back(arg);
}
for (const auto &pr : body->args.get_vals(name, args)) {
if (const define_body_t *existing = defines.find(pr.first)) {
macro_arg_stack.push({pr.first, *existing});
insert_input("`__restore_macro_arg ");
}
defines.add(pr.first, pr.second);
}
} else {
@ -725,6 +745,7 @@ frontend_verilog_preproc(std::istream &f,
defines.merge(pre_defines);
defines.merge(global_defines_cache);
macro_arg_stack_t macro_arg_stack;
std::vector<std::string> filename_stack;
// We are inside pass_level levels of satisfied ifdefs, and then within
// fail_level levels of unsatisfied ifdefs. The unsatisfied ones are
@ -828,7 +849,7 @@ frontend_verilog_preproc(std::istream &f,
if (tok == "`include") {
skip_spaces();
std::string fn = next_token(true);
while (try_expand_macro(defines, fn)) {
while (try_expand_macro(defines, macro_arg_stack, fn)) {
fn = next_token();
}
while (1) {
@ -935,7 +956,12 @@ frontend_verilog_preproc(std::istream &f,
continue;
}
if (try_expand_macro(defines, tok))
if (tok == "`__restore_macro_arg") {
restore_macro_arg(defines, macro_arg_stack);
continue;
}
if (try_expand_macro(defines, macro_arg_stack, tok))
continue;
output_code.push_back(tok);

View File

@ -42,6 +42,7 @@ struct define_map_t
// Add a definition, overwriting any existing definition for name.
void add(const std::string &name, const std::string &txt, const arg_map_t *args = nullptr);
void add(const std::string &name, const define_body_t &body);
// Merge in another map of definitions (which take precedence
// over anything currently defined).

View File

@ -0,0 +1,21 @@
// Taken from: https://github.com/YosysHQ/yosys/issues/2867
`define MIN(x, y) ((x) < (y) ? (x) : (y))
`define CEIL_DIV(x, y) (((x) / (y)) + `MIN((x) % (y), 1))
module pad_msg1 (input logic [`MIN(512*`CEIL_DIV(64, 512), 64)-1:0] x,
output logic [`MIN(512*`CEIL_DIV(64, 512), 64)-1:0] y);
assign y[63:0] = x;
endmodule
module pad_msg2 (input logic [((512*`CEIL_DIV(64, 512)) < (64) ? (512*`CEIL_DIV(64,512)) : (64))-1:0] x,
output logic [((512*`CEIL_DIV(64, 512)) < (64) ? (512*`CEIL_DIV(64,512)) : (64))-1:0] y);
assign y[63:0] = x;
endmodule
module top(...);
`define add(x) x +
input [3:0] A;
output [3:0] B;
assign B = `add(`add(3)A)A;
endmodule

View File

@ -0,0 +1,2 @@
logger -expect-no-warnings
read_verilog -sv macro_arg_tromp.sv