Skip to content

[xls/contrib] Tutorial: XLS[cc] state.

This tutorial is aimed at walking you through the implementation and synthesis into Verilog of a C++ function containing state.

XLS[cc] may infer that in order to achieve a particular implementation of a C++ function, operations may occur over multiple cycles and require additional proc state to be kept. Common constructs that may require this are static variables, or loops that aren't unrolled. In this tutorial we give an example using static variables.

C++ Source

Create a file named test_state.cc with the following contents.

template<typename T>
using OutputChannel = __xls_channel<T, __xls_channel_dir_Out>;

class TestBlock {
public:
    OutputChannel<int> out;

    int count = 0;

    #pragma hls_top
    void Run() {
        out.write(count);
        count++;
    }
};

Generate optimized XLS IR.

Use a combination of xlscc and opt_main to generate optimized XLS IR.

$ ./bazel-bin/xls/contrib/xlscc/xlscc test_state.cc \
  --block_from_class TestBlock --block_pb block.pb \
  > test_state.ir
$ ./bazel-bin/xls/tools/opt_main test_state.ir > test_state.opt.ir

Perform code-generation into a pipelined Verilog block.

In this case, we will generate a single-stage pipeline without input and output flops. This will result in a module with a 32-bit increment adder along with 32-bit of state.

$ ./bazel-bin/xls/tools/codegen_main test_state.opt.ir \
  --generator=pipeline \
  --delay_model="sky130" \
  --output_verilog_path=xls_counter.v \
  --module_name=xls_counter \
  --top=TestBlock_proc \
  --reset=rst \
  --reset_active_low=false \
  --reset_asynchronous=false \
  --reset_data_path=true \
  --pipeline_stages=1  \
  --flop_inputs=false \
  --flop_outputs=false

After running codegen, you should see a file named xls_counter.v with contents similar to the following.

module xls_counter(
  input wire clk,
  input wire rst,
  input wire out_rdy,
  output wire [31:0] out,
  output wire out_vld
);
  reg [31:0] __st__1;
  wire literal_43;
  wire literal_40;
  wire [31:0] add_37;
  wire pipeline_enable;
  assign literal_43 = 1'h1;
  assign literal_40 = 1'h1;
  assign add_37 = __st__1 + 32'h0000_0001;
  assign pipeline_enable = literal_43 & literal_40 & out_rdy & (literal_43 & literal_40 & out_rdy);
  always_ff @ (posedge clk) begin
    if (rst) begin
      __st__1 <= 32'h0000_0000;
    end else begin
      __st__1 <= pipeline_enable ? add_37 : __st__1;
    end
  end
  assign out = __st__1;
  assign out_vld = literal_40 & literal_43 & 1'h1;
endmodule

Additional XLS[cc] examples.

For developers, it is possible to check if a specific feature is supported by checking translator_static_test.cc and translator_proc_test.cc for unit tests.