adds drivers with inverted output

This commit is contained in:
hneemann 2023-11-08 09:15:18 +01:00
parent 4cefc1e140
commit d65caa2c4d
13 changed files with 219 additions and 15 deletions

View File

@ -257,6 +257,12 @@ public final class Keys {
public static final Key<Boolean> INVERT_OUTPUT public static final Key<Boolean> INVERT_OUTPUT
= new Key<>("invertOutput", true); = new Key<>("invertOutput", true);
/**
* inverts the output of an inverter
*/
public static final Key<Boolean> INVERT_DRIVER_OUTPUT
= new Key<>("invertDriverOutput", false).useTranslationOf(INVERT_OUTPUT).allowGroupEdit();
/** /**
* The real time frequency of the clock * The real time frequency of the clock
*/ */

View File

@ -30,11 +30,13 @@ public class Driver extends Node implements Element, Countable {
input("sel")) input("sel"))
.addAttribute(Keys.ROTATE) .addAttribute(Keys.ROTATE)
.addAttribute(Keys.BITS) .addAttribute(Keys.BITS)
.addAttribute(Keys.INVERT_DRIVER_OUTPUT)
.addAttribute(Keys.FLIP_SEL_POSITON) .addAttribute(Keys.FLIP_SEL_POSITON)
.supportsHDL(); .supportsHDL();
private final ObservableValue output; private final ObservableValue output;
private final int bits; private final int bits;
private final boolean invertOut;
private ObservableValue input; private ObservableValue input;
private ObservableValue selIn; private ObservableValue selIn;
private long value; private long value;
@ -50,6 +52,7 @@ public class Driver extends Node implements Element, Countable {
output = new ObservableValue("out", bits) output = new ObservableValue("out", bits)
.setToHighZ() .setToHighZ()
.setPinDescription(DESCRIPTION); .setPinDescription(DESCRIPTION);
invertOut = attributes.get(Keys.INVERT_DRIVER_OUTPUT);
} }
@Override @Override
@ -62,8 +65,12 @@ public class Driver extends Node implements Element, Countable {
public void writeOutputs() throws NodeException { public void writeOutputs() throws NodeException {
if (isOutHighZ(sel)) if (isOutHighZ(sel))
output.setToHighZ(); output.setToHighZ();
else else {
output.setValue(value); if (invertOut)
output.setValue(~value);
else
output.setValue(value);
}
} }
/** /**

View File

@ -24,6 +24,7 @@ public class DriverInvSel extends Driver {
input("sel")) input("sel"))
.addAttribute(Keys.ROTATE) .addAttribute(Keys.ROTATE)
.addAttribute(Keys.BITS) .addAttribute(Keys.BITS)
.addAttribute(Keys.INVERT_DRIVER_OUTPUT)
.addAttribute(Keys.FLIP_SEL_POSITON) .addAttribute(Keys.FLIP_SEL_POSITON)
.supportsHDL(); .supportsHDL();

View File

@ -27,6 +27,7 @@ public class DriverShape implements Shape {
private final boolean invertedInput; private final boolean invertedInput;
private final PinDescriptions inputs; private final PinDescriptions inputs;
private final PinDescriptions outputs; private final PinDescriptions outputs;
private final boolean invertedOutput;
private Pins pins; private Pins pins;
/** /**
@ -53,6 +54,7 @@ public class DriverShape implements Shape {
this.outputs = outputs; this.outputs = outputs;
this.bottom = attr.get(Keys.FLIP_SEL_POSITON); this.bottom = attr.get(Keys.FLIP_SEL_POSITON);
this.invertedInput = invertedInput; this.invertedInput = invertedInput;
this.invertedOutput = attr.get(Keys.INVERT_DRIVER_OUTPUT);
} }
@Override @Override
@ -61,7 +63,10 @@ public class DriverShape implements Shape {
pins = new Pins(); pins = new Pins();
pins.add(new Pin(new Vector(-SIZE, 0), inputs.get(0))); pins.add(new Pin(new Vector(-SIZE, 0), inputs.get(0)));
pins.add(new Pin(new Vector(0, bottom ? SIZE : -SIZE), inputs.get(1))); pins.add(new Pin(new Vector(0, bottom ? SIZE : -SIZE), inputs.get(1)));
pins.add(new Pin(new Vector(SIZE, 0), outputs.get(0))); if (invertedOutput)
pins.add(new Pin(new Vector(SIZE * 2, 0), outputs.get(0)));
else
pins.add(new Pin(new Vector(SIZE, 0), outputs.get(0)));
} }
return pins; return pins;
} }
@ -90,5 +95,11 @@ public class DriverShape implements Shape {
else else
graphic.drawLine(new Vector(0, -SIZE), new Vector(0, -7), Style.NORMAL); graphic.drawLine(new Vector(0, -SIZE), new Vector(0, -7), Style.NORMAL);
} }
if (invertedOutput) {
graphic.drawCircle(new Vector(SIZE + 1, 4 - SIZE2),
new Vector(SIZE + 1 + (SIZE2 - 4) * 2, SIZE2 - 4), Style.NORMAL);
graphic.drawLine(new Vector(SIZE + 1 + (SIZE2 - 4) * 2, 0), new Vector(SIZE * 2, 0), Style.NORMAL);
}
} }
} }

View File

@ -21,5 +21,5 @@ module <?= moduleName ?>
input sel, input sel,
output <?= bitRange ?>out output <?= bitRange ?>out
); );
assign out = (sel == 1'b1)? in : <?= zval ?>; assign out = (sel == 1'b1)? <? if (elem.invertDriverOutput) { ?>~ <?- } ?>in : <?= zval ?>;
endmodule endmodule

View File

@ -21,5 +21,5 @@ module <?= moduleName ?>
input sel, input sel,
output <?= bitRange ?>out output <?= bitRange ?>out
); );
assign out = (sel == 1'b0)? in : <?= zval ?>; assign out = (sel == 1'b0)? <? if (elem.invertDriverOutput) { ?>~ <?- } ?>in : <?= zval ?>;
endmodule endmodule

View File

@ -16,5 +16,5 @@ end <?=entityName?>;
architecture Behavioral of <?=entityName?> is architecture Behavioral of <?=entityName?> is
begin begin
p_out <= p_in when sel = '1' else <? if (elem.Bits=1) { ?>'Z'<?} else {?>(others => 'Z')<? } ?>; p_out <= <? if (elem.invertDriverOutput) { ?>NOT <? } ?>p_in when sel = '1' else <? if (elem.Bits=1) { ?>'Z'<?} else {?>(others => 'Z')<? } ?>;
end Behavioral; end Behavioral;

View File

@ -16,5 +16,5 @@ end <?=entityName?>;
architecture Behavioral of <?=entityName?> is architecture Behavioral of <?=entityName?> is
begin begin
p_out <= p_in when sel = '0' else <? if (elem.Bits=1) { ?>'Z'<?} else {?>(others => 'Z')<? } ?>; p_out <= <? if (elem.invertDriverOutput) { ?>NOT <? } ?>p_in when sel = '0' else <? if (elem.Bits=1) { ?>'Z'<?} else {?>(others => 'Z')<? } ?>;
end Behavioral; end Behavioral;

View File

@ -11,6 +11,7 @@ import de.neemann.digital.core.extern.ProcessStarter;
import de.neemann.digital.gui.Settings; import de.neemann.digital.gui.Settings;
import de.neemann.digital.hdl.model2.HDLException; import de.neemann.digital.hdl.model2.HDLException;
import de.neemann.digital.hdl.printer.CodePrinter; import de.neemann.digital.hdl.printer.CodePrinter;
import de.neemann.digital.hdl.printer.CodePrinterStr;
import de.neemann.digital.integration.FileScanner; import de.neemann.digital.integration.FileScanner;
import de.neemann.digital.integration.Resources; import de.neemann.digital.integration.Resources;
import de.neemann.digital.integration.TestExamples; import de.neemann.digital.integration.TestExamples;
@ -39,7 +40,7 @@ public class VerilogSimulatorTest extends TestCase {
/* /*
public void testDebug() throws Exception { public void testDebug() throws Exception {
File file = new File(Resources.getRoot(), "/dig/test/vhdl/pinControl/simple.dig"); File file = new File(Resources.getRoot(), "/dig/test/vhdl/driver1inv.dig");
ToBreakRunner br = new ToBreakRunner(file); ToBreakRunner br = new ToBreakRunner(file);
System.out.println(new VerilogGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit())); System.out.println(new VerilogGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit()));
@ -51,8 +52,8 @@ public class VerilogSimulatorTest extends TestCase {
File examples = new File(Resources.getRoot(), "/dig/test/vhdl"); File examples = new File(Resources.getRoot(), "/dig/test/vhdl");
try { try {
int tested = new FileScanner(this::checkVerilogExport).noOutput().scan(examples); int tested = new FileScanner(this::checkVerilogExport).noOutput().scan(examples);
assertEquals(68, tested); assertEquals(70, tested);
assertEquals(58, testBenches); assertEquals(60, testBenches);
} catch (FileScanner.SkipAllException e) { } catch (FileScanner.SkipAllException e) {
// if iverilog is not installed its also ok // if iverilog is not installed its also ok
} }

View File

@ -32,7 +32,7 @@ public class VHDLSimulatorTest extends TestCase {
/* /*
public void testDebug() throws Exception { public void testDebug() throws Exception {
File file = new File(Resources.getRoot(), "dig/external/ghdl/ghdlFile.dig"); File file = new File(Resources.getRoot(), "/dig/test/vhdl/driver2inv.dig");
ToBreakRunner br = new ToBreakRunner(file); ToBreakRunner br = new ToBreakRunner(file);
System.out.println(new VHDLGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit())); System.out.println(new VHDLGenerator(br.getLibrary(), new CodePrinterStr(true)).export(br.getCircuit()));
@ -44,8 +44,8 @@ public class VHDLSimulatorTest extends TestCase {
File examples = new File(Resources.getRoot(), "/dig/test/vhdl"); File examples = new File(Resources.getRoot(), "/dig/test/vhdl");
try { try {
int tested = new FileScanner(this::checkVHDLExport).noOutput().scan(examples); int tested = new FileScanner(this::checkVHDLExport).noOutput().scan(examples);
assertEquals(68, tested); assertEquals(70, tested);
assertEquals(58, testBenches); assertEquals(60, testBenches);
} catch (FileScanner.SkipAllException e) { } catch (FileScanner.SkipAllException e) {
// if ghdl is not installed its also ok // if ghdl is not installed its also ok
} }

View File

@ -51,8 +51,8 @@ public class TestExamples extends TestCase {
*/ */
public void testTestExamples() throws Exception { public void testTestExamples() throws Exception {
File examples = new File(Resources.getRoot(), "/dig/test"); File examples = new File(Resources.getRoot(), "/dig/test");
assertEquals(214, new FileScanner(this::check).scan(examples)); assertEquals(216, new FileScanner(this::check).scan(examples));
assertEquals(197, testCasesInFiles); assertEquals(199, testCasesInFiles);
} }
/** /**

View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<circuit>
<version>2</version>
<attributes/>
<visualElements>
<visualElement>
<elementName>Driver</elementName>
<elementAttributes>
<entry>
<string>invertDriverOutput</string>
<boolean>true</boolean>
</entry>
</elementAttributes>
<pos x="380" y="160"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>I</string>
</entry>
</elementAttributes>
<pos x="340" y="160"/>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>O</string>
</entry>
</elementAttributes>
<pos x="440" y="160"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>S</string>
</entry>
</elementAttributes>
<pos x="340" y="100"/>
</visualElement>
<visualElement>
<elementName>Testcase</elementName>
<elementAttributes>
<entry>
<string>Testdata</string>
<testData>
<dataString>S I O
0 0 Z
0 1 Z
1 0 1
1 1 0</dataString>
</testData>
</entry>
</elementAttributes>
<pos x="340" y="220"/>
</visualElement>
</visualElements>
<wires>
<wire>
<p1 x="420" y="160"/>
<p2 x="440" y="160"/>
</wire>
<wire>
<p1 x="340" y="160"/>
<p2 x="360" y="160"/>
</wire>
<wire>
<p1 x="340" y="100"/>
<p2 x="380" y="100"/>
</wire>
<wire>
<p1 x="380" y="100"/>
<p2 x="380" y="140"/>
</wire>
</wires>
<measurementOrdering/>
</circuit>

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<circuit>
<version>2</version>
<attributes/>
<visualElements>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>I</string>
</entry>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="340" y="160"/>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>O</string>
</entry>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="440" y="160"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>S</string>
</entry>
</elementAttributes>
<pos x="340" y="100"/>
</visualElement>
<visualElement>
<elementName>Testcase</elementName>
<elementAttributes>
<entry>
<string>Testdata</string>
<testData>
<dataString>S I O
1 0 Z
1 1 Z
0 0 0xf
0 1 0xe
0 4 0xb
</dataString>
</testData>
</entry>
</elementAttributes>
<pos x="340" y="220"/>
</visualElement>
<visualElement>
<elementName>DriverInvSel</elementName>
<elementAttributes>
<entry>
<string>invertDriverOutput</string>
<boolean>true</boolean>
</entry>
<entry>
<string>Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="380" y="160"/>
</visualElement>
</visualElements>
<wires>
<wire>
<p1 x="420" y="160"/>
<p2 x="440" y="160"/>
</wire>
<wire>
<p1 x="340" y="160"/>
<p2 x="360" y="160"/>
</wire>
<wire>
<p1 x="340" y="100"/>
<p2 x="380" y="100"/>
</wire>
<wire>
<p1 x="380" y="100"/>
<p2 x="380" y="140"/>
</wire>
</wires>
<measurementOrdering/>
</circuit>