// Every construct the formatter has a rule for, in the shapes the SystemRDL 2.0
// spec uses for them. Written in the formatter's own output style: formatting
// this file must change nothing, which is what `the_output_style_is_a_fixed_point`
// asserts.
// The preprocessor directives (spec Table 32). Each owns its line and its
// payload is kept byte for byte -- a macro body is substitution text, not code,
// so the spacing inside one is the author's.
`include "other.rdl"
`define MY_WIDTH 32
`define MY_RANGE(hi, lo) hi:lo
`undef OLD_WIDTH
property my_udp {
component = field | reg;
type = string;
default = "x";
};
struct base {
longint unsigned a;
};
abstract struct derived : base {
string b[];
};
// Struct literals exist to give a struct-typed UDP a value (spec 6.3.2.4).
property struct_udp {
component = field;
type = base;
default = base'{ a: 1 };
};
enum my_enum {
IDLE = 0;
BUSY = 1 {
name = "Busy";
desc = "The block is busy";
};
};
constraint named_c {
this > 0;
this inside { 1, 2, [3:4] };
this inside my_enum;
a = 1;
};
reg my_reg #(
longint unsigned WIDTH = 32,
boolean SPLIT = true
) {
regwidth = WIDTH;
field {
sw = rw; hw = r;
desc = "Status flags";
} STATUS[7:0] = 8'hA5;
field {} COUNT[15:8] = 0x0;
};
reg small #(longint unsigned W = 8) {
regwidth = W;
};
addrmap top #(string ext_path = "ext_block") {
name = "Top level map";
hdl_path = "int_block";
default regwidth = 32;
my_reg ctrl @ 0x0;
my_reg data[4] @ 0x10 += 0x4 %= 0x8;
small #(.W(16)) s1 @ 0x40;
my_reg #(
.WIDTH(8),
.SPLIT(false)
) s2 @ 0x50;
external my_reg ext @ 0x60;
alias ctrl my_reg al @ 0x70;
ctrl.STATUS->sw = rw;
ctrl.STATUS->hdl_path_slice = '{ "rtl_f1_1", "rtl_f1_0" };
// Concatenation builds an HDL path out of a parameter (spec 14.1.2).
reg {
hdl_path = { ext_path, ".external_reg" };
field {
hdl_path_slice = '{ "field1" };
} f1[0:0];
} external external_reg @ 0x80;
constraint {
this < 8;
} c1, c2;
};
// The remaining expression forms, which never break however long they get.
addrmap exprs {
a = W * 2 + (X - 1);
b = c ? d : e;
f = -g;
h = bit'(i);
j = 32'(k);
l = { 2{ m } };
n = my_enum::IDLE;
};
// A macro reference is an atom: it may stand for a value, or for a name, since
// what it expands to is unknowable without the definitions. A directive inside
// a body is indented with the code around it.
addrmap macros {
`include "regs.rdl"
reg {
field {} data[`MY_WIDTH - 1:0];
field {} limit[`MAX(3, 4):0];
} r1;
`MY_REG_T r2;
};
// A conditional is laid out like any other directive: on its own line, at the
// indentation of the code around it, and with both branches kept, since which
// one survives depends on definitions that live in another file.
`ifndef MY_MAP_DEFINED
addrmap conditional {
`ifdef WITH_STATUS
my_reg status @ 0x0;
`else
my_reg reserved @ 0x0;
`endif
};
`endif