IP-XACT register model¶
This example starts from a checked-in IP-XACT component rather than
SystemRDL. PeakRDL imports the standard IP-XACT memory map and the cpptb
exporter generates the same typed C++ RAL used by the other register examples.
The user does not author an intermediate .rdl file or check in generated C++.
The complete source is under examples/ipxact_regfile/:
ipxact_regfile/
├── component.xml # authored IP-XACT contract
├── ipxact_regfile.sv # authored APB4 RTL
├── testbench.cpp # generated-model APB test
├── model_contract.cpp # simulator-free fake-master check
├── cpptb.toml
└── systemverilog/
└── ipxact_regfile_sv_tb.sv # matching direct-SV sequence
build/cpptb/ipxact_regfile/
├── generated/ipxact_regs.hpp # generated typed model
├── obj/ # C++ DPI simulator
└── systemverilog_obj/ # pure-SV simulator
Use the generated hierarchy¶
The generated model preserves the IP-XACT address-block hierarchy. Ordinary registers, register arrays, and memory all use typed handles:
ipxact_regs::RegModel regs{test, master};
co_await regs.registers.control.write(0x5u);
regs.registers.control.enable.stage(1u);
regs.registers.control.mode.stage(
ipxact_regs::mode_enum_t::STREAM);
co_await regs.registers.control.update();
co_await regs.registers.threshold.at<2>().write(0x1234u);
constexpr std::array<uint32_t, 3> packet{
0x1122'3344u, 0xa5a5'5a5au, 0xcafe'babeu};
co_await regs.scratchpad.write(
4, std::span<const uint32_t>{packet});
The register array index is checked at compile time. The memory call writes
three words beginning at logical entry 4, which maps to absolute addresses
0x110, 0x114, and 0x118.
Compare the executable sequence¶
The two benches issue the same APB4 transfers and both finish at 410 ns. The C++ version uses the generated contract; the SV version spells out the corresponding addresses and bus operations.
ipxact_regs::RegModel regs{test, master};
co_await regs.registers.control.write(0x5u);
const auto control = co_await regs.registers.control.read();
test.expect_eq("control readback", control.data, 0x5u);
regs.registers.control.mode.stage(
ipxact_regs::mode_enum_t::STREAM);
co_await regs.registers.control.update();
co_await regs.registers.threshold.at<2>().write(0x1234u);
co_await regs.scratchpad.write(4, packet);
co_await regs.scratchpad.read(4, readback);
test.expect_eq("scratchpad readback", readback, packet);
apb_write_word(9'h000, 32'h0000_0005);
apb_read_word(9'h000, data);
expect_eq("control readback", data, 32'h0000_0005);
// Combined enable/mode field update.
apb_write_word(9'h000, 32'h0000_0003);
apb_write_word(9'h028, 32'h0000_1234);
for (int unsigned index = 0; index < 3; index++)
apb_write_word(9'h110 + (index * 4), packet[index]);
for (int unsigned index = 0; index < 3; index++) begin
apb_read_word(9'h110 + (index * 4), data);
expect_eq("scratchpad readback", data, packet[index]);
end
Run the complete example from the repository root:
make cpptb-ipxact-regfile-model-test
make cpp-dpi-ipxact-regfile-run
make cpp-dpi-ipxact-regfile-sv-run
Or run make test inside examples/ipxact_regfile/.
Compatibility boundary¶
cpptb accepts IP-XACT through the installed PeakRDL importer. Registers, fields, arrays, standard access and reset properties, enumerated values, and native memory address blocks all reach the generated model in this regression. The checked-in example is regenerated, compiled against a fake master, and run over APB in the normal test suite.
Vendor extensions are not automatically portable. PeakRDL must first map an extension into SystemRDL semantics before the cpptb exporter can preserve it. When a project depends on custom IP-XACT properties, add that mapping to the import layer or keep a SystemRDL source contract; silently assuming an unknown extension affected the model is not supported.
See Register generation for naming controls and Memory and register models for the complete generated API.