mirror of https://github.com/YosysHQ/yosys.git
proc_rom: Add special handling of const-0 address bits.
This commit is contained in:
parent
06ef3f264a
commit
9450f308f0
|
@ -46,10 +46,6 @@ struct RomWorker
|
|||
log_debug("rejecting switch: no cases\n");
|
||||
return;
|
||||
}
|
||||
if (GetSize(sw->signal) > 30) {
|
||||
log_debug("rejecting switch: address too wide\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// A switch can be converted into ROM when:
|
||||
//
|
||||
|
@ -70,9 +66,15 @@ struct RomWorker
|
|||
}
|
||||
}
|
||||
|
||||
int swsigbits = 0;
|
||||
for (int i = 0; i < GetSize(sw->signal); i++)
|
||||
if (sw->signal[i] != State::S0)
|
||||
swsigbits = i + 1;
|
||||
|
||||
dict<int, Const> vals;
|
||||
Const default_val;
|
||||
bool got_default = false;
|
||||
int maxaddr = 0;
|
||||
for (auto cs : sw->cases) {
|
||||
if (!cs->switches.empty()) {
|
||||
log_debug("rejecting switch: has nested switches\n");
|
||||
|
@ -105,10 +107,21 @@ struct RomWorker
|
|||
log_debug("rejecting switch: case value has undef bits\n");
|
||||
return;
|
||||
}
|
||||
int a = addr.as_int();
|
||||
Const c = addr.as_const();
|
||||
while (GetSize(c) && c.bits.back() == State::S0)
|
||||
c.bits.pop_back();
|
||||
if (GetSize(c) > swsigbits)
|
||||
continue;
|
||||
if (GetSize(c) > 30) {
|
||||
log_debug("rejecting switch: address too large\n");
|
||||
return;
|
||||
}
|
||||
int a = c.as_int();
|
||||
if (vals.count(a))
|
||||
continue;
|
||||
vals[a] = val;
|
||||
if (a > maxaddr)
|
||||
maxaddr = a;
|
||||
}
|
||||
if (cs->compare.empty()) {
|
||||
default_val = val;
|
||||
|
@ -116,8 +129,8 @@ struct RomWorker
|
|||
break;
|
||||
}
|
||||
}
|
||||
int total = 1 << GetSize(sw->signal);
|
||||
if (!got_default && GetSize(vals) != total) {
|
||||
int abits = ceil_log2(maxaddr + 1);
|
||||
if (!got_default && (swsigbits > 30 || GetSize(vals) != (1 << swsigbits))) {
|
||||
log_debug("rejecting switch: not all values are covered\n");
|
||||
return;
|
||||
}
|
||||
|
@ -127,18 +140,18 @@ struct RomWorker
|
|||
log_debug("rejecting switch: not enough values\n");
|
||||
return;
|
||||
}
|
||||
if (total / GetSize(vals) > 4) {
|
||||
if ((1 << abits) / GetSize(vals) > 4) {
|
||||
log_debug("rejecting switch: not enough density\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Ok, let's do it.
|
||||
SigSpec rdata = module->addWire(NEW_ID, GetSize(lhs));
|
||||
Mem mem(module, NEW_ID, GetSize(lhs), 0, total);
|
||||
Mem mem(module, NEW_ID, GetSize(lhs), 0, 1 << abits);
|
||||
mem.attributes = sw->attributes;
|
||||
|
||||
Const init_data;
|
||||
for (int i = 0; i < total; i++) {
|
||||
for (int i = 0; i < mem.size; i++) {
|
||||
auto it = vals.find(i);
|
||||
if (it == vals.end()) {
|
||||
log_assert(got_default);
|
||||
|
@ -157,7 +170,7 @@ struct RomWorker
|
|||
mem.inits.push_back(std::move(init));
|
||||
|
||||
MemRd rd;
|
||||
rd.addr = sw->signal;
|
||||
rd.addr = sw->signal.extract(0, abits);
|
||||
rd.data = rdata;
|
||||
rd.init_value = Const(State::Sx, GetSize(lhs));
|
||||
rd.arst_value = Const(State::Sx, GetSize(lhs));
|
||||
|
@ -168,10 +181,22 @@ struct RomWorker
|
|||
for (auto cs: sw->cases)
|
||||
delete cs;
|
||||
sw->cases.clear();
|
||||
sw->signal = SigSpec();
|
||||
RTLIL::CaseRule *cs = new RTLIL::CaseRule;
|
||||
cs->actions.push_back(SigSig(lhs, rdata));
|
||||
sw->cases.push_back(cs);
|
||||
sw->signal = sw->signal.extract(0, swsigbits);
|
||||
if (abits == GetSize(sw->signal)) {
|
||||
sw->signal = SigSpec();
|
||||
RTLIL::CaseRule *cs = new RTLIL::CaseRule;
|
||||
cs->actions.push_back(SigSig(lhs, rdata));
|
||||
sw->cases.push_back(cs);
|
||||
} else {
|
||||
sw->signal = sw->signal.extract_end(abits);
|
||||
RTLIL::CaseRule *cs = new RTLIL::CaseRule;
|
||||
cs->compare.push_back(Const(State::S0, GetSize(sw->signal)));
|
||||
cs->actions.push_back(SigSig(lhs, rdata));
|
||||
sw->cases.push_back(cs);
|
||||
RTLIL::CaseRule *cs2 = new RTLIL::CaseRule;
|
||||
cs2->actions.push_back(SigSig(lhs, default_val));
|
||||
sw->cases.push_back(cs2);
|
||||
}
|
||||
|
||||
count += 1;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ hierarchy -auto-top
|
|||
|
||||
design -save orig
|
||||
proc
|
||||
select -assert-count 1 t:$memrd_v2
|
||||
memory
|
||||
opt_dff
|
||||
design -stash postopt
|
||||
|
@ -41,3 +42,148 @@ proc -norom
|
|||
design -stash preopt
|
||||
|
||||
equiv_opt -assert -run prepare: dummy
|
||||
|
||||
|
||||
|
||||
design -reset
|
||||
|
||||
read_verilog << EOT
|
||||
|
||||
module top(input [3:0] a, input en, output [7:0] d);
|
||||
|
||||
always @*
|
||||
if (en)
|
||||
case(a)
|
||||
4'h0: d <= 8'h12;
|
||||
4'h1: d <= 8'h34;
|
||||
4'h2: d <= 8'h56;
|
||||
4'h3: d <= 8'h78;
|
||||
4'h4: d <= 8'h9a;
|
||||
4'h5: d <= 8'hbc;
|
||||
4'h6: d <= 8'hde;
|
||||
4'h7: d <= 8'hff;
|
||||
4'h8: d <= 8'h61;
|
||||
4'h9: d <= 8'h49;
|
||||
4'ha: d <= 8'h36;
|
||||
4'hb: d <= 8'h81;
|
||||
4'hc: d <= 8'h8c;
|
||||
default: d <= 8'h11;
|
||||
endcase
|
||||
else
|
||||
d <= 0;
|
||||
|
||||
endmodule
|
||||
|
||||
EOT
|
||||
|
||||
hierarchy -auto-top
|
||||
|
||||
design -save orig
|
||||
proc
|
||||
select -assert-count 1 t:$memrd_v2
|
||||
memory
|
||||
opt_dff
|
||||
design -stash postopt
|
||||
design -load orig
|
||||
proc -norom
|
||||
design -stash preopt
|
||||
|
||||
equiv_opt -assert -run prepare: dummy
|
||||
|
||||
|
||||
|
||||
design -reset
|
||||
|
||||
read_verilog << EOT
|
||||
|
||||
module top(input [31:0] a, input en, output [7:0] d);
|
||||
|
||||
always @*
|
||||
if (en)
|
||||
case(a)
|
||||
0: d <= 8'h12;
|
||||
1: d <= 8'h34;
|
||||
2: d <= 8'h56;
|
||||
3: d <= 8'h78;
|
||||
4: d <= 8'h9a;
|
||||
5: d <= 8'hbc;
|
||||
6: d <= 8'hde;
|
||||
7: d <= 8'hff;
|
||||
8: d <= 8'h61;
|
||||
9: d <= 8'h49;
|
||||
10: d <= 8'h36;
|
||||
11: d <= 8'h81;
|
||||
12: d <= 8'h8c;
|
||||
default: d <= 8'h11;
|
||||
endcase
|
||||
else
|
||||
d <= 0;
|
||||
|
||||
endmodule
|
||||
|
||||
EOT
|
||||
|
||||
hierarchy -auto-top
|
||||
|
||||
design -save orig
|
||||
proc
|
||||
select -assert-count 1 t:$memrd_v2
|
||||
memory
|
||||
opt_dff
|
||||
design -stash postopt
|
||||
design -load orig
|
||||
proc -norom
|
||||
design -stash preopt
|
||||
|
||||
equiv_opt -assert -run prepare: dummy
|
||||
|
||||
|
||||
design -reset
|
||||
|
||||
read_verilog << EOT
|
||||
|
||||
module top(input [3:0] a, input en, output [7:0] d);
|
||||
|
||||
always @*
|
||||
if (en)
|
||||
case(a)
|
||||
'h0: d <= 8'h12;
|
||||
'h1: d <= 8'h34;
|
||||
'h2: d <= 8'h56;
|
||||
'h3: d <= 8'h78;
|
||||
'h4: d <= 8'h9a;
|
||||
'h5: d <= 8'hbc;
|
||||
'h6: d <= 8'hde;
|
||||
'h7: d <= 8'hff;
|
||||
'h8: d <= 8'h61;
|
||||
'h9: d <= 8'h49;
|
||||
'ha: d <= 8'h36;
|
||||
'hb: d <= 8'h81;
|
||||
'hc: d <= 8'h8c;
|
||||
'hd: d <= 8'ha9;
|
||||
'he: d <= 8'h99;
|
||||
'hf: d <= 8'h51;
|
||||
endcase
|
||||
else
|
||||
d <= 0;
|
||||
|
||||
endmodule
|
||||
|
||||
EOT
|
||||
|
||||
hierarchy -auto-top
|
||||
|
||||
design -save orig
|
||||
proc
|
||||
select -assert-count 1 t:$memrd_v2
|
||||
memory
|
||||
opt_dff
|
||||
design -stash postopt
|
||||
design -load orig
|
||||
proc -norom
|
||||
design -stash preopt
|
||||
|
||||
equiv_opt -assert -run prepare: dummy
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue