| #include "lut.h" |
| |
| #include <sstream> |
| |
| #include "vtr_assert.h" |
| #include "vpr_error.h" |
| #include "vtr_util.h" |
| |
| namespace fasm { |
| |
| Lut::Lut(size_t num_inputs) : num_inputs_(num_inputs), table_(1 << num_inputs, vtr::LogicValue::DONT_CARE) {} |
| |
| void Lut::SetOutput(const std::vector<vtr::LogicValue> &inputs, vtr::LogicValue value) { |
| VTR_ASSERT(inputs.size() == num_inputs_); |
| std::vector<size_t> dont_care_inputs; |
| dont_care_inputs.reserve(num_inputs_); |
| |
| for(size_t address = 0; address < table_.size(); ++address) { |
| bool match = true; |
| for(size_t input = 0; input < inputs.size(); ++input) { |
| if(inputs[input] == vtr::LogicValue::TRUE && (address & (1 << input)) == 0) { |
| match = false; |
| break; |
| } else if(inputs[input] == vtr::LogicValue::FALSE && (address & (1 << input)) != 0) { |
| match = false; |
| break; |
| } |
| } |
| |
| if(match) { |
| VTR_ASSERT(table_[address] == vtr::LogicValue::DONT_CARE || table_[address] == value); |
| table_[address] = value; |
| } |
| } |
| } |
| |
| void Lut::CreateWire(size_t input_pin) { |
| std::vector<vtr::LogicValue> inputs(num_inputs_, vtr::LogicValue::DONT_CARE); |
| inputs[input_pin] = vtr::LogicValue::FALSE; |
| SetOutput(inputs, vtr::LogicValue::FALSE); |
| inputs[input_pin] = vtr::LogicValue::TRUE; |
| SetOutput(inputs, vtr::LogicValue::TRUE); |
| } |
| |
| void Lut::SetConstant(vtr::LogicValue value) { |
| std::vector<vtr::LogicValue> inputs(num_inputs_, vtr::LogicValue::DONT_CARE); |
| SetOutput(inputs, value); |
| } |
| |
| const LogicVec & Lut::table() { |
| // Make sure the entire table is defined. |
| for(size_t address = 0; address < table_.size(); ++address) { |
| if(table_[address] == vtr::LogicValue::DONT_CARE) { |
| table_[address] = vtr::LogicValue::FALSE; |
| } |
| } |
| |
| return table_; |
| } |
| |
| LutOutputDefinition::LutOutputDefinition(std::string definition) { |
| // Parse LUT.INIT[63:0] into |
| // fasm_feature = LUT.INIT |
| // start_bit = 0 |
| // end_bit = 63 |
| // num_inputs = log2(end_bit-start_bit+1) |
| |
| size_t slice_start = definition.find_first_of('['); |
| size_t slice = std::string::npos; |
| size_t slice_end = std::string::npos; |
| |
| if(slice_start != std::string::npos) { |
| slice = definition.find_first_of(':', slice_start); |
| } |
| if(slice != std::string::npos) { |
| slice_end = definition.find_first_of(']'); |
| } |
| |
| if(slice_start == std::string::npos || |
| slice == std::string::npos || |
| slice_end == std::string::npos || |
| slice_start+1 > slice-1 || |
| slice+1 > slice_end-1) { |
| vpr_throw( |
| VPR_ERROR_OTHER, __FILE__, __LINE__, |
| "Could not parse LUT definition %s", |
| definition.c_str()); |
| } |
| |
| fasm_feature = definition.substr(0, slice_start); |
| std::string end_bit_str = definition.substr(slice_start+1, (slice-1)-(slice_start+1)+1); |
| std::string start_bit_str = definition.substr(slice+1, (slice_end-1)-(slice+1)+1); |
| |
| end_bit = vtr::atoi(end_bit_str); |
| start_bit = vtr::atoi(start_bit_str); |
| |
| int width = end_bit - start_bit + 1; |
| |
| // If an exact power of two, only 1 bit will be set in width. |
| if(width < 0 || __builtin_popcount(width) != 1) { |
| vpr_throw( |
| VPR_ERROR_OTHER, __FILE__, __LINE__, |
| "Invalid LUT start_bit %d and end_bit %d, not a power of 2 width.", |
| start_bit, end_bit); |
| } |
| |
| // For exact power's of 2, ctz (count trailing zeros) is log2(width). |
| num_inputs = __builtin_ctz(width); |
| } |
| |
| std::string LutOutputDefinition::CreateWire(int input) const { |
| Lut lut(num_inputs); |
| lut.CreateWire(input); |
| |
| return CreateInit(lut.table()); |
| } |
| |
| std::string LutOutputDefinition::CreateConstant(vtr::LogicValue value) const { |
| Lut lut(num_inputs); |
| lut.SetConstant(value); |
| return CreateInit(lut.table()); |
| } |
| |
| std::string LutOutputDefinition::CreateInit(const LogicVec & table) const { |
| if(table.size() != (1u << num_inputs)) { |
| vpr_throw( |
| VPR_ERROR_OTHER, __FILE__, __LINE__, |
| "LUT with %d inputs requires a INIT LogicVec of size %d, got %d", |
| num_inputs, (1 << num_inputs), table.size()); |
| } |
| std::stringstream ss; |
| ss << fasm_feature << "[" << end_bit << ":" << start_bit << "]=" << table; |
| |
| return ss.str(); |
| } |
| |
| } // namespace fasm |