Skip to content

Commit a182e90

Browse files
committed
Refactor lut.cpp and fix warnings.
Signed-off-by: Keith Rothman <[email protected]>
1 parent 42efb4b commit a182e90

File tree

6 files changed

+184
-137
lines changed

6 files changed

+184
-137
lines changed

utils/fasm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ project("genfasm")
66
add_library(fasm
77
src/fasm.cpp
88
src/fasm.h
9+
src/lut.cpp
910
src/lut.h
1011
)
1112
target_include_directories(fasm PUBLIC src)

utils/fasm/src/fasm.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "fasm.h"
2323

24+
namespace fasm {
2425

2526
FasmWriterVisitor::FasmWriterVisitor(std::ostream& f) : os_(f) {}
2627

@@ -123,7 +124,8 @@ std::string FasmWriterVisitor::build_clb_prefix(const t_pb_graph_node* pb_graph_
123124

124125
auto fasm_prefix_unsplit = pb_type->meta->get("fasm_prefix")->front().as_string();
125126
auto fasm_prefix = vtr::split(fasm_prefix_unsplit, " ");
126-
if(fasm_prefix.size() != pb_type->num_pb) {
127+
VTR_ASSERT(pb_type->num_pb >= 0);
128+
if(fasm_prefix.size() != static_cast<size_t>(pb_type->num_pb)) {
127129
vpr_throw(VPR_ERROR_OTHER,
128130
__FILE__, __LINE__, "fasm_prefix = %s, num_pb = %d",
129131
fasm_prefix_unsplit.c_str(), pb_type->num_pb);
@@ -192,10 +194,10 @@ void FasmWriterVisitor::visit_all_impl(const t_pb_route *pb_route, const t_pb* p
192194
if(io_pin != nullptr) {
193195
auto& route = pb_route[io_pin->pin_count_in_cluster];
194196
const int num_inputs = *route.pb_graph_pin->parent_node->num_input_pins;
195-
const auto &lut_definition = find_lut(route.pb_graph_pin->parent_node);
196-
VTR_ASSERT(lut_definition.num_inputs == num_inputs);
197+
const auto *lut_definition = find_lut(route.pb_graph_pin->parent_node);
198+
VTR_ASSERT(lut_definition->num_inputs == num_inputs);
197199

198-
output_fasm_features(lut_definition.CreateWire(route.pb_graph_pin->pin_number));
200+
output_fasm_features(lut_definition->CreateWire(route.pb_graph_pin->pin_number));
199201
}
200202
}
201203

@@ -335,7 +337,7 @@ static const t_metadata_dict *get_fasm_type(const t_pb_graph_node* pb_graph_node
335337
return nullptr;
336338
}
337339

338-
const LutOutputDefinition& FasmWriterVisitor::find_lut(const t_pb_graph_node* pb_graph_node) {
340+
const LutOutputDefinition* FasmWriterVisitor::find_lut(const t_pb_graph_node* pb_graph_node) {
339341
const t_pb_graph_node* orig_pb_graph_node = pb_graph_node;
340342
(void)orig_pb_graph_node;
341343

@@ -397,7 +399,7 @@ const LutOutputDefinition& FasmWriterVisitor::find_lut(const t_pb_graph_node* pb
397399
auto string_at_node = vtr::string_fmt("%s[%d]", pb_graph_node->pb_type->name, pb_graph_node->placement_index);
398400
for(const auto &lut : iter->second) {
399401
if(lut.first == string_at_node) {
400-
return lut.second;
402+
return &lut.second;
401403
}
402404
}
403405
}
@@ -407,6 +409,7 @@ const LutOutputDefinition& FasmWriterVisitor::find_lut(const t_pb_graph_node* pb
407409

408410
vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
409411
"Failed to find LUT output definition.");
412+
return nullptr;
410413
}
411414

412415
static const t_pb_route *find_pb_route(const t_pb* pb) {
@@ -438,12 +441,12 @@ void FasmWriterVisitor::check_for_lut(const t_pb* atom) {
438441
const t_model* model = atom_ctx.nlist.block_model(atom_blk_id);
439442
if (model->name == std::string(MODEL_NAMES)) {
440443
VTR_ASSERT(atom->pb_graph_node != nullptr);
441-
const auto &lut_definition = find_lut(atom->pb_graph_node);
442-
VTR_ASSERT(lut_definition.num_inputs == *atom->pb_graph_node->num_input_pins);
444+
const auto *lut_definition = find_lut(atom->pb_graph_node);
445+
VTR_ASSERT(lut_definition->num_inputs == *atom->pb_graph_node->num_input_pins);
443446

444447
const t_pb_route *pb_route = find_pb_route(atom);
445-
LogicVec lut_mask = lut_outputs(atom, lut_definition.num_inputs, pb_route);
446-
output_fasm_features(lut_definition.CreateInit(lut_mask));
448+
LogicVec lut_mask = lut_outputs(atom, lut_definition->num_inputs, pb_route);
449+
output_fasm_features(lut_definition->CreateInit(lut_mask));
447450
}
448451
}
449452

@@ -577,3 +580,5 @@ void FasmWriterVisitor::output_fasm_features(std::string features) const {
577580
}
578581
}
579582
}
583+
584+
} // namespace fasm

utils/fasm/src/fasm.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include "netlist_writer.h"
1616
#include "lut.h"
1717

18+
namespace fasm {
19+
1820
class FasmWriterVisitor : public NetlistVisitor {
1921

2022
public:
@@ -37,7 +39,7 @@ class FasmWriterVisitor : public NetlistVisitor {
3739
void output_fasm_mux(std::string fasm_mux, t_interconnect *interconnect, t_pb_graph_pin *mux_input_pin);
3840
void walk_routing();
3941
std::string build_clb_prefix(const t_pb_graph_node* pb_graph_node) const;
40-
const LutOutputDefinition& find_lut(const t_pb_graph_node* pb_graph_node);
42+
const LutOutputDefinition* find_lut(const t_pb_graph_node* pb_graph_node);
4143

4244
std::ostream& os_;
4345

@@ -51,4 +53,6 @@ class FasmWriterVisitor : public NetlistVisitor {
5153
std::map<const t_pb_type*, std::vector<std::pair<std::string, LutOutputDefinition>>> lut_definitions_;
5254
};
5355

56+
} // namespace fasm
57+
5458
#endif // FASM_H

utils/fasm/src/lut.cpp

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#include "lut.h"
2+
3+
namespace fasm {
4+
5+
Lut::Lut(size_t num_inputs) : num_inputs_(num_inputs), table_(1 << num_inputs, vtr::LogicValue::DONT_CARE) {}
6+
7+
void Lut::SetOutput(const std::vector<vtr::LogicValue> &inputs, vtr::LogicValue value) {
8+
VTR_ASSERT(inputs.size() == num_inputs_);
9+
std::vector<size_t> dont_care_inputs;
10+
dont_care_inputs.reserve(num_inputs_);
11+
12+
for(size_t address = 0; address < table_.size(); ++address) {
13+
bool match = true;
14+
for(size_t input = 0; input < inputs.size(); ++input) {
15+
if(inputs[input] == vtr::LogicValue::TRUE && (address & (1 << input)) == 0) {
16+
match = false;
17+
break;
18+
} else if(inputs[input] == vtr::LogicValue::FALSE && (address & (1 << input)) != 0) {
19+
match = false;
20+
break;
21+
}
22+
}
23+
24+
if(match) {
25+
VTR_ASSERT(table_[address] == vtr::LogicValue::DONT_CARE || table_[address] == value);
26+
table_[address] = value;
27+
}
28+
}
29+
}
30+
31+
void Lut::CreateWire(size_t input_pin) {
32+
std::vector<vtr::LogicValue> inputs(num_inputs_, vtr::LogicValue::DONT_CARE);
33+
inputs[input_pin] = vtr::LogicValue::FALSE;
34+
SetOutput(inputs, vtr::LogicValue::FALSE);
35+
inputs[input_pin] = vtr::LogicValue::TRUE;
36+
SetOutput(inputs, vtr::LogicValue::TRUE);
37+
}
38+
39+
void Lut::SetConstant(vtr::LogicValue value) {
40+
std::vector<vtr::LogicValue> inputs(num_inputs_, vtr::LogicValue::DONT_CARE);
41+
SetOutput(inputs, value);
42+
}
43+
44+
const LogicVec & Lut::table() {
45+
// Make sure the entire table is defined.
46+
for(size_t address = 0; address < table_.size(); ++address) {
47+
if(table_[address] == vtr::LogicValue::DONT_CARE) {
48+
table_[address] = vtr::LogicValue::FALSE;
49+
}
50+
}
51+
52+
return table_;
53+
}
54+
55+
LutOutputDefinition::LutOutputDefinition(std::string definition) {
56+
// Parse LUT.INIT[63:0] into
57+
// fasm_feature = LUT.INIT
58+
// start_bit = 0
59+
// end_bit = 63
60+
// num_inputs = log2(end_bit-start_bit+1)
61+
62+
size_t slice_start = definition.find_first_of('[');
63+
size_t slice = std::string::npos;
64+
size_t slice_end = std::string::npos;
65+
66+
if(slice_start != std::string::npos) {
67+
slice = definition.find_first_of(':', slice_start);
68+
}
69+
if(slice != std::string::npos) {
70+
slice_end = definition.find_first_of(']');
71+
}
72+
73+
if(slice_start == std::string::npos ||
74+
slice == std::string::npos ||
75+
slice_end == std::string::npos ||
76+
slice_start+1 > slice-1 ||
77+
slice+1 > slice_end-1) {
78+
vpr_throw(
79+
VPR_ERROR_OTHER, __FILE__, __LINE__,
80+
"Could not parse LUT definition %s",
81+
definition.c_str());
82+
}
83+
84+
fasm_feature = definition.substr(0, slice_start);
85+
std::string end_bit_str = definition.substr(slice_start+1, (slice-1)-(slice_start+1)+1);
86+
std::string start_bit_str = definition.substr(slice+1, (slice_end-1)-(slice+1)+1);
87+
88+
end_bit = vtr::atoi(end_bit_str);
89+
start_bit = vtr::atoi(start_bit_str);
90+
91+
int width = end_bit - start_bit + 1;
92+
93+
// If an exact power of two, only 1 bit will be set in width.
94+
if(width < 0 || __builtin_popcount(width) != 1) {
95+
vpr_throw(
96+
VPR_ERROR_OTHER, __FILE__, __LINE__,
97+
"Invalid LUT start_bit %d and end_bit %d, not a power of 2 width.",
98+
start_bit, end_bit);
99+
}
100+
101+
// For exact power's of 2, ctz (count trailing zeros) is log2(width).
102+
num_inputs = __builtin_ctz(width);
103+
}
104+
105+
std::string LutOutputDefinition::CreateWire(int input) const {
106+
Lut lut(num_inputs);
107+
lut.CreateWire(input);
108+
109+
return CreateInit(lut.table());
110+
}
111+
112+
std::string LutOutputDefinition::CreateConstant(vtr::LogicValue value) const {
113+
Lut lut(num_inputs);
114+
lut.SetConstant(value);
115+
return CreateInit(lut.table());
116+
}
117+
118+
std::string LutOutputDefinition::CreateInit(const LogicVec & table) const {
119+
if(table.size() != (1u << num_inputs)) {
120+
vpr_throw(
121+
VPR_ERROR_OTHER, __FILE__, __LINE__,
122+
"LUT with %d inputs requires a INIT LogicVec of size %d, got %d",
123+
num_inputs, (1 << num_inputs), table.size());
124+
}
125+
std::stringstream ss;
126+
ss << fasm_feature << "[" << end_bit << ":" << start_bit << "]=" << table;
127+
128+
return ss.str();
129+
}
130+
131+
} // namespace fasm

0 commit comments

Comments
 (0)