Skip to content

Commit b9afda7

Browse files
Sean Purser-Haskellcopybara-github
authored andcommitted
[xlscc] Add option to set control channel FIFO depth for multi-block designs.
Sets a default FIFO depth of 0 for sub-block control channels, and adds the [[hls_control_channel_depth(N)]] Clang attribute to allow the depth to be explicitly set. xlscc represents C++ control flow by putting IO operations in a serial token chain according to the order in the code. This also applies to IO operations for calls to sub-blocks, specifically in this case the send on the control channel. PiperOrigin-RevId: 706841832
1 parent 2fc5099 commit b9afda7

File tree

11 files changed

+518
-132
lines changed

11 files changed

+518
-132
lines changed

xls/contrib/xlscc/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ cc_library(
139139
"//xls/ir:value_utils",
140140
"//xls/solvers:z3_ir_translator",
141141
"//xls/solvers:z3_utils",
142+
"@com_google_absl//absl/algorithm:container",
142143
"@com_google_absl//absl/base",
143144
"@com_google_absl//absl/base:core_headers",
144145
"@com_google_absl//absl/container:btree",

xls/contrib/xlscc/cc_parser.cc

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,75 @@ static clang::ParsedAttrInfoRegistry::Add<XlsBlockAttrInfo> hls_block(
720720
"hls_block",
721721
"Marks a function its own HLS block, below the top in the hierarchy.");
722722

723+
struct XlsControlChannelDepthAttrInfo : public clang::ParsedAttrInfo {
724+
XlsControlChannelDepthAttrInfo() {
725+
// GNU-style __attribute__(("hls_control_channel_depth")) and C++/C23-style
726+
// [[hls_control_channel_depth]] and [[xlscc::hls_control_channel_depth]]
727+
// supported.
728+
static constexpr Spelling S[] = {
729+
{clang::ParsedAttr::AS_GNU, "hls_control_channel_depth"},
730+
{clang::ParsedAttr::AS_C23, "hls_control_channel_depth"},
731+
{clang::ParsedAttr::AS_CXX11, "hls_control_channel_depth"},
732+
{clang::ParsedAttr::AS_CXX11, "xlscc::hls_control_channel_depth"}};
733+
Spellings = S;
734+
NumArgs = 1;
735+
}
736+
737+
bool diagAppertainsToDecl(clang::Sema& S, const clang::ParsedAttr& Attr,
738+
const clang::Decl* D) const override {
739+
// This attribute appertains to functions only.
740+
if (!isa<clang::FunctionDecl>(D)) {
741+
S.Diag(Attr.getLoc(), clang::diag::warn_attribute_wrong_decl_type_str)
742+
<< Attr << Attr.isRegularKeywordAttribute() << "functions";
743+
return false;
744+
}
745+
return true;
746+
}
747+
748+
AttrHandling handleDeclAttribute(
749+
clang::Sema& S, clang::Decl* D,
750+
const clang::ParsedAttr& Attr) const override {
751+
clang::Attr* Result;
752+
if (!CreateAttr(S, Attr, Result)) {
753+
return AttributeNotApplied;
754+
}
755+
D->addAttr(Result);
756+
return AttributeApplied;
757+
}
758+
759+
private:
760+
bool CreateAttr(clang::Sema& S, const clang::ParsedAttr& Attr,
761+
clang::Attr*& Result) const {
762+
CHECK_EQ(Attr.getNumArgs(), 1);
763+
764+
auto invalid_argument = [&]() {
765+
unsigned ID = S.getDiagnostics().getCustomDiagID(
766+
clang::DiagnosticsEngine::Error,
767+
"the argument to the 'hls_control_channel_depth' attribute must be "
768+
"an integer >= 1");
769+
S.Diag(Attr.getLoc(), ID);
770+
return false;
771+
};
772+
773+
clang::Expr* args[1];
774+
if (!Attr.isArgExpr(0)) {
775+
return invalid_argument();
776+
}
777+
args[0] = Attr.getArgAsExpr(0);
778+
if (!args[0]->isIntegerConstantExpr(S.Context) ||
779+
!args[0]->EvaluateKnownConstInt(S.Context).isStrictlyPositive()) {
780+
return invalid_argument();
781+
}
782+
Result = clang::AnnotateAttr::Create(S.Context, "hls_control_channel_depth",
783+
args, /*ArgsSize=*/1, Attr.getRange());
784+
return true;
785+
}
786+
};
787+
static clang::ParsedAttrInfoRegistry::Add<XlsControlChannelDepthAttrInfo>
788+
hls_control_channel_depth("hls_control_channel_depth",
789+
"Sets the depth of the control channel FIFO for "
790+
"a sub-block. Default is 0.");
791+
723792
class HlsArgsPragmaHandler : public clang::PragmaHandler {
724793
public:
725794
explicit HlsArgsPragmaHandler(const std::string& pragma_name,

xls/contrib/xlscc/translate_loops.cc

Lines changed: 23 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ namespace xlscc {
6767

6868
absl::Status Translator::GenerateIR_Loop(
6969
bool always_first_iter, const clang::Stmt* loop_stmt,
70-
clang::ArrayRef<const clang::Attr*> attrs, const clang::Stmt* init,
70+
clang::ArrayRef<const clang::AnnotateAttr*> attrs, const clang::Stmt* init,
7171
const clang::Expr* cond_expr, const clang::Stmt* inc,
7272
const clang::Stmt* body, const clang::PresumedLoc& presumed_loc,
7373
const xls::SourceInfo& loc, clang::ASTContext& ctx) {
@@ -79,54 +79,33 @@ absl::Status Translator::GenerateIR_Loop(
7979
}
8080
}
8181

82+
bool is_asap = HasAnnotation(attrs, "xlscc_asap");
83+
8284
int64_t init_interval = -1;
85+
XLS_ASSIGN_OR_RETURN(std::optional<int64_t> init_interval_optional,
86+
GetAnnotationWithNonNegativeIntegerParam(
87+
attrs, "hls_pipeline_init_interval", loc, ctx));
88+
89+
if (init_interval_optional.has_value()) {
90+
init_interval = init_interval_optional.value();
91+
} else {
92+
// Pipelined loops can inherit their initiation interval from enclosing
93+
// loops, so they can be allowed not to have a #pragma.
94+
CHECK(!context().in_pipelined_for_body ||
95+
(context().outer_pipelined_loop_init_interval > 0));
96+
init_interval = context().outer_pipelined_loop_init_interval;
97+
}
98+
8399
int64_t unroll_factor = context().for_loops_default_unroll
84100
? std::numeric_limits<int64_t>::max()
85101
: 0;
86-
bool is_asap = false;
87-
for (const clang::Attr* attr : attrs) {
88-
if (const clang::AnnotateAttr* annotate =
89-
llvm::dyn_cast<clang::AnnotateAttr>(attr);
90-
annotate != nullptr) {
91-
if (annotate->getAnnotation() == "hls_unroll") {
92-
if (annotate->args_size() == 0) {
93-
unroll_factor = std::numeric_limits<int64_t>::max();
94-
} else if (annotate->args_size() > 1) {
95-
return absl::InvalidArgumentError(
96-
"hls_unroll must have at most one argument");
97-
} else if (clang::Expr::EvalResult result;
98-
(*annotate->args().begin())->EvaluateAsInt(result, ctx) &&
99-
result.Val.getInt().isStrictlyPositive() &&
100-
result.Val.getInt().isRepresentableByInt64()) {
101-
unroll_factor = result.Val.getInt().getExtValue();
102-
} else {
103-
return absl::InvalidArgumentError(
104-
"hls_unroll argument (if provided) must be a positive integer");
105-
}
106-
continue;
107-
}
108-
109-
if (annotate->getAnnotation() == "hls_pipeline_init_interval") {
110-
if (annotate->args_size() != 1) {
111-
return absl::InvalidArgumentError(
112-
"hls_pipeline_init_interval must have exactly one argument");
113-
}
114-
clang::Expr::EvalResult result;
115-
if (!(*annotate->args().begin())->EvaluateAsInt(result, ctx) ||
116-
!result.Val.getInt().isStrictlyPositive() ||
117-
!result.Val.getInt().isRepresentableByInt64()) {
118-
return absl::InvalidArgumentError(
119-
"the argument to the 'hls_pipeline_init_interval' attribute must "
120-
"be an integer >= 1");
121-
}
122-
init_interval = result.Val.getInt().getExtValue();
123-
continue;
124-
}
102+
XLS_ASSIGN_OR_RETURN(
103+
std::optional<int64_t> unroll_factor_optional,
104+
GetAnnotationWithNonNegativeIntegerParam(attrs, "hls_unroll", loc, ctx,
105+
/*default_value=*/1));
125106

126-
if (annotate->getAnnotation() == "xlscc_asap") {
127-
is_asap = true;
128-
}
129-
}
107+
if (unroll_factor_optional.has_value()) {
108+
unroll_factor = unroll_factor_optional.value();
130109
}
131110

132111
if (unroll_factor > 0) {
@@ -141,14 +120,6 @@ absl::Status Translator::GenerateIR_Loop(
141120
body, ctx, loc);
142121
}
143122

144-
// Pipelined loops can inherit their initiation interval from enclosing
145-
// loops, so they can be allowed not to have a #pragma.
146-
if (init_interval < 0) {
147-
CHECK(!context().in_pipelined_for_body ||
148-
(context().outer_pipelined_loop_init_interval > 0));
149-
init_interval = context().outer_pipelined_loop_init_interval;
150-
}
151-
152123
if (init_interval <= 0) {
153124
return absl::UnimplementedError(
154125
ErrorMessage(loc, "Loop statement missing #pragma or attribute"));

0 commit comments

Comments
 (0)