mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-12 20:18:20 +00:00
booth: Replace the default signed architecture
Generalize what was formerly the unsigned-only architecture to support both signed and unsigned multiplication, use that as default, and set aside the special low-power architecture that was formerly used for signed multipliers.
This commit is contained in:
parent
f50894d8bf
commit
48b73be8c6
|
@ -276,18 +276,12 @@ struct BoothPassWorker {
|
||||||
}
|
}
|
||||||
log_assert(GetSize(Y) == required_op_size);
|
log_assert(GetSize(Y) == required_op_size);
|
||||||
|
|
||||||
if (!is_signed) /* unsigned multiplier */
|
CreateBoothMult(module,
|
||||||
CreateBoothUMult(module,
|
A, // multiplicand
|
||||||
A, // multiplicand
|
B, // multiplier(scanned)
|
||||||
B, // multiplier(scanned)
|
Y, // result
|
||||||
Y // result
|
is_signed
|
||||||
);
|
);
|
||||||
else /* signed multiplier */
|
|
||||||
CreateBoothSMult(module,
|
|
||||||
A, // multiplicand
|
|
||||||
B, // multiplier(scanned)
|
|
||||||
Y // result (sized)
|
|
||||||
);
|
|
||||||
|
|
||||||
module->remove(cell);
|
module->remove(cell);
|
||||||
booth_counter++;
|
booth_counter++;
|
||||||
|
@ -295,24 +289,23 @@ struct BoothPassWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Build Unsigned Multiplier.
|
Build Multiplier.
|
||||||
-------------------------
|
-------------------------
|
||||||
Create a booth unsigned multiplier.
|
Uses a generic booth multiplier
|
||||||
Uses a generic booth multiplier with
|
|
||||||
extra row of decoders and extended multiplier
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void CreateBoothUMult(RTLIL::Module *module,
|
void CreateBoothMult(RTLIL::Module *module,
|
||||||
SigSpec X, // multiplicand
|
SigSpec X, // multiplicand
|
||||||
SigSpec Y, // multiplier
|
SigSpec Y, // multiplier
|
||||||
SigSpec Z)
|
SigSpec Z,
|
||||||
|
bool is_signed)
|
||||||
{ // result
|
{ // result
|
||||||
int z_sz = Z.size();
|
int z_sz = Z.size();
|
||||||
|
|
||||||
SigSpec one_int, two_int, s_int, sb_int;
|
SigSpec one_int, two_int, s_int, sb_int;
|
||||||
int encoder_count = 0;
|
int encoder_count = 0;
|
||||||
|
|
||||||
BuildBoothUMultEncoders(Y, one_int, two_int, s_int, sb_int, module, encoder_count);
|
BuildBoothMultEncoders(Y, one_int, two_int, s_int, sb_int, module, encoder_count, is_signed);
|
||||||
|
|
||||||
// Build the decoder rows
|
// Build the decoder rows
|
||||||
// format of each Partial product to be passed to CSA
|
// format of each Partial product to be passed to CSA
|
||||||
|
@ -326,7 +319,7 @@ struct BoothPassWorker {
|
||||||
|
|
||||||
// Row 0: special case 1. Format S/.S.S.C.Data
|
// Row 0: special case 1. Format S/.S.S.C.Data
|
||||||
SigSpec ppij_row_0;
|
SigSpec ppij_row_0;
|
||||||
BuildBoothUMultDecoderRow0(module, X, s_int, sb_int, one_int, two_int, ppij_row_0);
|
BuildBoothMultDecoderRow0(module, X, s_int, sb_int, one_int, two_int, ppij_row_0, is_signed);
|
||||||
|
|
||||||
// data, shift, sign
|
// data, shift, sign
|
||||||
ppij_int.push_back(std::make_tuple(ppij_row_0, 0, s_int[0]));
|
ppij_int.push_back(std::make_tuple(ppij_row_0, 0, s_int[0]));
|
||||||
|
@ -335,9 +328,10 @@ struct BoothPassWorker {
|
||||||
// format 1,S.Data.shift = encoder_ix*2,sign = sb_int[i]
|
// format 1,S.Data.shift = encoder_ix*2,sign = sb_int[i]
|
||||||
SigSpec ppij_row_n;
|
SigSpec ppij_row_n;
|
||||||
|
|
||||||
BuildBoothUMultDecoderRowN(module,
|
BuildBoothMultDecoderRowN(module,
|
||||||
X, // multiplicand
|
X, // multiplicand
|
||||||
one_int[i], two_int[i], s_int[i], sb_int[i], ppij_row_n, i
|
one_int[i], two_int[i], s_int[i], sb_int[i], ppij_row_n, i,
|
||||||
|
is_signed
|
||||||
);
|
);
|
||||||
// data, shift, sign
|
// data, shift, sign
|
||||||
ppij_int.push_back(std::make_tuple(ppij_row_n, i * 2, s_int[i]));
|
ppij_int.push_back(std::make_tuple(ppij_row_n, i * 2, s_int[i]));
|
||||||
|
@ -373,6 +367,7 @@ struct BoothPassWorker {
|
||||||
// Debug code: Dump out the csa trees
|
// Debug code: Dump out the csa trees
|
||||||
// DumpCSATrees(debug_csa_trees);
|
// DumpCSATrees(debug_csa_trees);
|
||||||
// Build the CPA to do the final accumulation.
|
// Build the CPA to do the final accumulation.
|
||||||
|
|
||||||
BuildCPA(module, s_vec, c_vec, Z);
|
BuildCPA(module, s_vec, c_vec, Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,11 +375,12 @@ struct BoothPassWorker {
|
||||||
Build Row 0 of decoders
|
Build Row 0 of decoders
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void BuildBoothUMultDecoderRow0(RTLIL::Module *module,
|
void BuildBoothMultDecoderRow0(RTLIL::Module *module,
|
||||||
SigSpec X, // multiplicand
|
SigSpec X, // multiplicand
|
||||||
SigSpec s_int, SigSpec sb_int, SigSpec one_int,
|
SigSpec s_int, SigSpec sb_int, SigSpec one_int,
|
||||||
SigSpec two_int, SigSpec &ppij_vec)
|
SigSpec two_int, SigSpec &ppij_vec, bool is_signed)
|
||||||
{
|
{
|
||||||
|
(void)sb_int;
|
||||||
(void)module;
|
(void)module;
|
||||||
int x_sz = GetSize(X);
|
int x_sz = GetSize(X);
|
||||||
SigBit ppij;
|
SigBit ppij;
|
||||||
|
@ -397,21 +393,32 @@ struct BoothPassWorker {
|
||||||
ppij_vec.append(Bur4d_n(stringf("row0_dec_%d", i), X[i], X[i - 1],
|
ppij_vec.append(Bur4d_n(stringf("row0_dec_%d", i), X[i], X[i - 1],
|
||||||
one_int[0], two_int[0], s_int[0]));
|
one_int[0], two_int[0], s_int[0]));
|
||||||
|
|
||||||
|
|
||||||
// The redundant bit. Duplicate decoding of last bit.
|
// The redundant bit. Duplicate decoding of last bit.
|
||||||
ppij_vec.append(Bur4d_msb("row0_dec_msb", X[x_sz - 1], two_int[0], s_int[0]));
|
if (!is_signed) {
|
||||||
|
ppij_vec.append(Bur4d_msb("row0_dec_msb", X.msb(), two_int[0], s_int[0]));
|
||||||
|
} else {
|
||||||
|
ppij_vec.append(Bur4d_n("row0_dec_msb", X.msb(), X.msb(),
|
||||||
|
one_int[0], two_int[0], s_int[0]));
|
||||||
|
}
|
||||||
|
|
||||||
// append the sign bits
|
// append the sign bits
|
||||||
ppij_vec.append(s_int[0]);
|
if (is_signed) {
|
||||||
ppij_vec.append(s_int[0]);
|
SigBit e = module->XorGate(NEW_ID, s_int[0], module->AndGate(NEW_ID, X.msb(), module->OrGate(NEW_ID, two_int[0], one_int[0])));
|
||||||
ppij_vec.append(sb_int[0]);
|
ppij_vec.append({module->NotGate(NEW_ID, e), e, e});
|
||||||
|
} else {
|
||||||
|
// append the sign bits
|
||||||
|
ppij_vec.append({module->NotGate(NEW_ID, s_int[0]), s_int[0], s_int[0]});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a generic row of decoders.
|
// Build a generic row of decoders.
|
||||||
|
|
||||||
void BuildBoothUMultDecoderRowN(RTLIL::Module *module,
|
void BuildBoothMultDecoderRowN(RTLIL::Module *module,
|
||||||
SigSpec X, // multiplicand
|
SigSpec X, // multiplicand
|
||||||
SigSpec one_int, SigSpec two_int, SigSpec s_int, SigSpec sb_int,
|
SigSpec one_int, SigSpec two_int, SigSpec s_int, SigSpec sb_int,
|
||||||
SigSpec &ppij_vec, int row_ix)
|
SigSpec &ppij_vec, int row_ix,
|
||||||
|
bool is_signed)
|
||||||
{
|
{
|
||||||
(void)module;
|
(void)module;
|
||||||
int x_sz = GetSize(X);
|
int x_sz = GetSize(X);
|
||||||
|
@ -424,13 +431,14 @@ struct BoothPassWorker {
|
||||||
ppij_vec.append(Bur4d_n(stringf("row_%d_dec_%d", row_ix, i), X[i], X[i - 1],
|
ppij_vec.append(Bur4d_n(stringf("row_%d_dec_%d", row_ix, i), X[i], X[i - 1],
|
||||||
one_int, two_int, s_int));
|
one_int, two_int, s_int));
|
||||||
|
|
||||||
// redundant bit
|
if (!is_signed) { // redundant bit
|
||||||
ppij_vec.append(Bur4d_msb("row_dec_red", X[x_sz - 1], two_int, s_int));
|
ppij_vec.append(Bur4d_msb("row_dec_red", X[x_sz - 1], two_int, s_int));
|
||||||
|
} else {
|
||||||
|
ppij_vec.append(Bur4d_n(stringf("row_%d_dec_msb", row_ix), X[x_sz - 1], X[x_sz - 1],
|
||||||
|
one_int, two_int, s_int));
|
||||||
|
}
|
||||||
|
|
||||||
// sign bit
|
ppij_vec.append(!is_signed ? sb_int[0] : module->XorGate(NEW_ID, sb_int, module->AndGate(NEW_ID, X.msb(), module->OrGate(NEW_ID, two_int, one_int))));
|
||||||
ppij_vec.append(sb_int);
|
|
||||||
|
|
||||||
// constant bit
|
|
||||||
ppij_vec.append(State::S1);
|
ppij_vec.append(State::S1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -807,12 +815,12 @@ struct BoothPassWorker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildBoothUMultEncoders(SigSpec Y, SigSpec &one_int, SigSpec &two_int,
|
void BuildBoothMultEncoders(SigSpec Y, SigSpec &one_int, SigSpec &two_int,
|
||||||
SigSpec &s_int, SigSpec &sb_int, RTLIL::Module *module, int &encoder_ix)
|
SigSpec &s_int, SigSpec &sb_int, RTLIL::Module *module, int &encoder_ix, bool is_signed)
|
||||||
{
|
{
|
||||||
int y_sz = GetSize(Y);
|
int y_sz = GetSize(Y);
|
||||||
|
|
||||||
for (int y_ix = 0; y_ix < y_sz;) {
|
for (int y_ix = 0; y_ix < (!is_signed ? y_sz : y_sz - 1);) {
|
||||||
std::string enc_name = stringf("bur_enc_%d", encoder_ix);
|
std::string enc_name = stringf("bur_enc_%d", encoder_ix);
|
||||||
|
|
||||||
two_int.append(module->addWire(NEW_ID_SUFFIX(stringf("two_int_%d", encoder_ix)), 1));
|
two_int.append(module->addWire(NEW_ID_SUFFIX(stringf("two_int_%d", encoder_ix)), 1));
|
||||||
|
@ -838,7 +846,7 @@ struct BoothPassWorker {
|
||||||
bool need_padded_cell = false;
|
bool need_padded_cell = false;
|
||||||
|
|
||||||
if (y_ix > y_sz - 1) {
|
if (y_ix > y_sz - 1) {
|
||||||
y0 = State::S0;
|
y0 = is_signed ? Y.msb() : State::S0;
|
||||||
need_padded_cell = false;
|
need_padded_cell = false;
|
||||||
} else {
|
} else {
|
||||||
y0 = Y[y_ix];
|
y0 = Y[y_ix];
|
||||||
|
@ -847,7 +855,7 @@ struct BoothPassWorker {
|
||||||
|
|
||||||
if (y_ix > y_sz - 1) {
|
if (y_ix > y_sz - 1) {
|
||||||
need_padded_cell = false;
|
need_padded_cell = false;
|
||||||
y1 = State::S0;
|
y1 = is_signed ? Y.msb() : State::S0;
|
||||||
} else {
|
} else {
|
||||||
y1 = Y[y_ix];
|
y1 = Y[y_ix];
|
||||||
y_ix++;
|
y_ix++;
|
||||||
|
@ -855,10 +863,10 @@ struct BoothPassWorker {
|
||||||
|
|
||||||
if (y_ix > y_sz - 1) {
|
if (y_ix > y_sz - 1) {
|
||||||
need_padded_cell = false;
|
need_padded_cell = false;
|
||||||
y2 = State::S0;
|
y2 = is_signed ? Y.msb() : State::S0;
|
||||||
} else {
|
} else {
|
||||||
if (y_ix == y_sz - 1)
|
if (y_ix == y_sz - 1)
|
||||||
need_padded_cell = true;
|
need_padded_cell = !is_signed;
|
||||||
else
|
else
|
||||||
need_padded_cell = false;
|
need_padded_cell = false;
|
||||||
y2 = Y[y_ix];
|
y2 = Y[y_ix];
|
||||||
|
|
Loading…
Reference in a new issue