74xx-liberty
74xx-liberty copied to clipboard
Improve arithmetic
Currently we only generate $add cells based on the 74AC283, but Yosys has a bunch of other things that we could look into.
Summary of the discussion so far as I understand it:
- 74181 does not match $alu but could in theory be hardwired for specific functions
- 74181 is not in production it seems, so hard to get
- The 74182 should make a good $lcu
- A 7485 comparison pass was tried, but slightly worse than plain logic
- But variables take over twice as much logic, so maybe worth it
- We could generate $sub with an inverter and adder
- Yosys could maybe figure this out by itself, but experimentation shows it just generates plain logic
I hope there is a way Yosys can be smarter about using the adder for other things. Multiplication also generates huge chunks of logic without a single adder. It'd probably be possible to implement multiplication ourselves in a techpass, but it'd be worth looking into letting Yosys do the heavy lifting.
I'm trying to debug an issue where everything gets optimized away if I use a multiplication in one particular case. Meanwhile I found this: https://github.com/YosysHQ/yosys/blob/master/techlibs/common/techmap.v#L260 so if we make a $lcu from 74182 it would get used already. But actually it's not like I can find 74182 for sale anywhere. Hmmm, I wonder why big commercial companies stopped producing obsolete logic chips...
Fun fact: counter <= counter + -1;
synthesizes to an adder, while counter <= counter - 1;
does not.
Just a comment with random things I want to look at later so I don't forget:
- [x] 8-input nand for comparison
- [x] JK flip-flop (does yosys understand them? useful?)
- [x] shift registers (what's pmux2shiftx and is shregmap something useful?)
- [x] counters (requires changes to yosys, currently only seems to count down)
Yosys is not happy with my J-K flip-flop. Probably not worth spending more time on. Was just a curiosity:
// 74HC73 dual J-K flip-flop with clear
cell(74HC73_2x1JKFFR) {
area: 5;
ff(IQ, IQN) {
clocked_on: "CLK";
next_state: "(IQ*J'*K')+(J*K')+(IQ'*J*K*)'";
clear: "C'";
}
pin(CLK) { direction: input; clock: true; }
pin(C) { direction: input; }
pin(J) { direction: input; }
pin(K) { direction: input; }
pin(Q) { direction: output; function: "IQ"; }
}
It was fine with me putting an 8-input NAND in, but never used it at all, even when writing ~&bus
, this is a bit unfortunate, as it could compact some comparisons. Not sure what to do with it.
// 74HC30 single 8-input NAND
cell(74HC30_1x1NAND8) {
area: 9;
pin(A) { direction: input; }
pin(B) { direction: input; }
pin(C) { direction: input; }
pin(D) { direction: input; }
pin(E) { direction: input; }
pin(F) { direction: input; }
pin(G) { direction: input; }
pin(H) { direction: input; }
pin(Y) { direction: output; function: "((((((((A*B)*C)*D)*D)*E)*F)*G)*H)'"; }
}