mirror of https://github.com/YosysHQ/yosys.git
verilog: save and restore overwritten macro arguments
This commit is contained in:
parent
a055145b95
commit
3156226233
|
@ -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 ¯o_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 ¯o_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);
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
logger -expect-no-warnings
|
||||
read_verilog -sv macro_arg_tromp.sv
|
Loading…
Reference in New Issue