diff --git a/include/circt/Dialect/Synth/CMakeLists.txt b/include/circt/Dialect/Synth/CMakeLists.txt index 6fb6d154abf8..42f8c523dd7a 100644 --- a/include/circt/Dialect/Synth/CMakeLists.txt +++ b/include/circt/Dialect/Synth/CMakeLists.txt @@ -12,6 +12,12 @@ add_circt_interface(SynthOpInterfaces) add_subdirectory(Transforms) set(LLVM_TARGET_DEFINITIONS Synth.td) + +mlir_tablegen(SynthEnums.h.inc -gen-enum-decls) +mlir_tablegen(SynthEnums.cpp.inc -gen-enum-defs) +add_public_tablegen_target(CIRCTSynthEnumsIncGen) +add_dependencies(circt-headers CIRCTSynthEnumsIncGen) + mlir_tablegen(SynthAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=synth) mlir_tablegen(SynthAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=synth) add_public_tablegen_target(CIRCTSynthAttrIncGen) diff --git a/include/circt/Dialect/Synth/Synth.td b/include/circt/Dialect/Synth/Synth.td index 7b0ee3dec5d5..55f960e46439 100644 --- a/include/circt/Dialect/Synth/Synth.td +++ b/include/circt/Dialect/Synth/Synth.td @@ -26,6 +26,7 @@ def Synth_Dialect : Dialect { let useDefaultAttributePrinterParser = 1; } +include "circt/Dialect/Synth/SynthEnums.td" include "circt/Dialect/Synth/SynthAttributes.td" include "circt/Dialect/Synth/SynthOps.td" diff --git a/include/circt/Dialect/Synth/SynthAttributes.h b/include/circt/Dialect/Synth/SynthAttributes.h index 9dc23ded8a39..d88e647bf164 100644 --- a/include/circt/Dialect/Synth/SynthAttributes.h +++ b/include/circt/Dialect/Synth/SynthAttributes.h @@ -9,6 +9,7 @@ #ifndef CIRCT_DIALECT_SYNTH_SYNTHATTRIBUTES_H #define CIRCT_DIALECT_SYNTH_SYNTHATTRIBUTES_H +#include "circt/Dialect/Synth/SynthEnums.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/BuiltinAttributes.h" diff --git a/include/circt/Dialect/Synth/SynthAttributes.td b/include/circt/Dialect/Synth/SynthAttributes.td index 46f1beb9fbc4..9844a3e554f2 100644 --- a/include/circt/Dialect/Synth/SynthAttributes.td +++ b/include/circt/Dialect/Synth/SynthAttributes.td @@ -12,6 +12,8 @@ include "mlir/IR/AttrTypeBase.td" include "mlir/IR/DialectBase.td" +include "mlir/IR/EnumAttr.td" +include "circt/Dialect/Synth/SynthEnums.td" // A single resolved 2D NLDM lookup table. Values are stored in row-major order // with dimensions index1.size x index2.size. @@ -45,5 +47,41 @@ def NLDMTimingArcAttr : AttrDef { "$riseTransition `,` $fallTransition `>`"; } +def PolarityAttr : AttrDef { + let mnemonic = "polarity"; + let summary = "Timing arc polarity"; + let parameters = (ins + "PolarityKind":$value + ); + let assemblyFormat = "`<` $value `>`"; +} + +def LinearTimingArcAttr : AttrDef { + let mnemonic = "linear_timing_arc"; + let summary = "A single simplified linear timing arc"; + let parameters = (ins + "::mlir::StringAttr":$pin, + "::mlir::StringAttr":$relatedPin, + "int64_t":$intrinsic, + "int64_t":$sensitivity, + "PolarityAttr":$polarity + ); + let assemblyFormat = + "`<` $pin `,` $relatedPin `,` $intrinsic `,` $sensitivity `,` " + "$polarity `>`"; +} + +def MappingCostAttr : AttrDef { + let mnemonic = "mapping_cost"; + let summary = "Simplified timing and area cost for tech mapping"; + let parameters = (ins + "::mlir::FloatAttr":$area, + "::mlir::ArrayAttr":$arcs, + "::mlir::DictionaryAttr":$inputCaps + ); + let assemblyFormat = + "`<` `area` `=` $area `,` `arcs` `=` $arcs `,` " + "`input_caps` `=` $inputCaps `>`"; +} #endif // CIRCT_DIALECT_SYNTH_SYNTHATTRIBUTES_TD diff --git a/include/circt/Dialect/Synth/SynthEnums.h b/include/circt/Dialect/Synth/SynthEnums.h new file mode 100644 index 000000000000..2433710e34c5 --- /dev/null +++ b/include/circt/Dialect/Synth/SynthEnums.h @@ -0,0 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef CIRCT_DIALECT_SYNTH_SYNTHENUMS_H +#define CIRCT_DIALECT_SYNTH_SYNTHENUMS_H + +#include "mlir/IR/BuiltinAttributes.h" +#include "llvm/ADT/StringRef.h" + +#include "circt/Dialect/Synth/SynthEnums.h.inc" + +#endif // CIRCT_DIALECT_SYNTH_SYNTHENUMS_H diff --git a/include/circt/Dialect/Synth/SynthEnums.td b/include/circt/Dialect/Synth/SynthEnums.td new file mode 100644 index 000000000000..fe3da7cd1c1c --- /dev/null +++ b/include/circt/Dialect/Synth/SynthEnums.td @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines Synth dialect specific enums. +// +//===----------------------------------------------------------------------===// + +#ifndef CIRCT_DIALECT_SYNTH_SYNTHENUMS_TD +#define CIRCT_DIALECT_SYNTH_SYNTHENUMS_TD + +include "mlir/IR/EnumAttr.td" + +let cppNamespace = "circt::synth" in { + +def Polarity_Positive : I32EnumAttrCase<"Positive", 0, "positive">; +def Polarity_Negative : I32EnumAttrCase<"Negative", 1, "negative">; + +def PolarityKindAttr : I32EnumAttr<"PolarityKind", "timing arc polarity", + [Polarity_Positive, Polarity_Negative]>; + +} + +#endif // CIRCT_DIALECT_SYNTH_SYNTHENUMS_TD diff --git a/integration_test/circt-synth/mapping-lec.mlir b/integration_test/circt-synth/mapping-lec.mlir index 4b34b1e047ee..6067c35fa2f3 100644 --- a/integration_test/circt-synth/mapping-lec.mlir +++ b/integration_test/circt-synth/mapping-lec.mlir @@ -15,29 +15,29 @@ // COMB_MUL_LUT: c1 == c2 // Set delay for binary and inv op to 5 so that others will be prioritized -hw.module @and_inv(in %a : i1, in %b : i1, out result : i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[5], [5]]}} { +hw.module @and_inv(in %a : i1, in %b : i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 5, 0, #synth.polarity>], input_caps = {}>} { %0 = synth.aig.and_inv %a, %b : i1 hw.output %0 : i1 } -hw.module @and_inv_n(in %a : i1, in %b : i1, out result : i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[5], [5]]}} { +hw.module @and_inv_n(in %a : i1, in %b : i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 5, 0, #synth.polarity>], input_caps = {}>} { %0 = synth.aig.and_inv not %a, %b : i1 hw.output %0 : i1 } -hw.module @and_inv_nn(in %a : i1, in %b : i1, out result : i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[5], [5]]}} { +hw.module @and_inv_nn(in %a : i1, in %b : i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 5, 0, #synth.polarity>], input_caps = {}>} { %0 = synth.aig.and_inv not %a, not %b : i1 hw.output %0 : i1 } -hw.module @nand_nand(in %a : i1, in %b : i1, in %c : i1, in %d: i1, out result : i1) attributes {hw.techlib.info = {area = 3.0 : f64, delay = [[1], [1], [1], [1]]}} { +hw.module @nand_nand(in %a : i1, in %b : i1, in %c : i1, in %d: i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 1, 0, #synth.polarity>, #synth.linear_timing_arc<"result", "c", 1, 0, #synth.polarity>, #synth.linear_timing_arc<"result", "d", 1, 0, #synth.polarity>], input_caps = {}>} { %0 = synth.aig.and_inv %a, %b : i1 %1 = synth.aig.and_inv %c, %d : i1 %2 = synth.aig.and_inv not %0, not %1 : i1 hw.output %2 : i1 } -hw.module @some(in %a : i1, in %b : i1, out result : i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[1], [1]]}} { +hw.module @some(in %a : i1, in %b : i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 1, 0, #synth.polarity>], input_caps = {}>} { %0 = synth.aig.and_inv not %a, not %b : i1 %1 = synth.aig.and_inv %a, %b : i1 %2 = synth.aig.and_inv not %0, not %1 : i1 diff --git a/lib/Dialect/Synth/CMakeLists.txt b/lib/Dialect/Synth/CMakeLists.txt index efa597205683..a4f378823fb4 100644 --- a/lib/Dialect/Synth/CMakeLists.txt +++ b/lib/Dialect/Synth/CMakeLists.txt @@ -15,6 +15,7 @@ add_circt_dialect_library(CIRCTSynth DEPENDS MLIRSynthIncGen MLIRSynthOpInterfacesIncGen + CIRCTSynthEnumsIncGen CIRCTSynthAttrIncGen LINK_COMPONENTS diff --git a/lib/Dialect/Synth/SynthDialect.cpp b/lib/Dialect/Synth/SynthDialect.cpp index fe17372f6344..5b99157c520c 100644 --- a/lib/Dialect/Synth/SynthDialect.cpp +++ b/lib/Dialect/Synth/SynthDialect.cpp @@ -9,6 +9,7 @@ #include "circt/Dialect/Synth/SynthDialect.h" #include "circt/Dialect/HW/HWOps.h" #include "circt/Dialect/Synth/SynthAttributes.h" +#include "circt/Dialect/Synth/SynthEnums.h" #include "circt/Dialect/Synth/SynthOps.h" #include "mlir/IR/DialectImplementation.h" @@ -41,3 +42,5 @@ Operation *SynthDialect::materializeConstant(OpBuilder &builder, #define GET_ATTRDEF_CLASSES #include "circt/Dialect/Synth/SynthAttributes.cpp.inc" + +#include "circt/Dialect/Synth/SynthEnums.cpp.inc" diff --git a/lib/Dialect/Synth/Transforms/TechMapper.cpp b/lib/Dialect/Synth/Transforms/TechMapper.cpp index 86dd8d35d99c..405c3a4987d6 100644 --- a/lib/Dialect/Synth/Transforms/TechMapper.cpp +++ b/lib/Dialect/Synth/Transforms/TechMapper.cpp @@ -12,18 +12,20 @@ // // The pass uses a cut-based algorithm with priority cuts and NPN canonical // forms for efficient pattern matching. It processes HWModuleOp instances with -// "hw.techlib.info" attributes as technology library patterns and maps +// "synth.mapping_cost" attributes as technology library patterns and maps // non-library modules to optimal gate implementations based on area and timing // optimization strategies. // //===----------------------------------------------------------------------===// #include "circt/Dialect/HW/HWOps.h" +#include "circt/Dialect/Synth/SynthAttributes.h" #include "circt/Dialect/Synth/Transforms/CutRewriter.h" #include "mlir/IR/Builders.h" #include "mlir/IR/Threading.h" #include "mlir/Support/WalkResult.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" #include @@ -188,48 +190,94 @@ struct TechMapperPass : public impl::TechMapperBase { SmallVector> libraryPatterns; unsigned maxInputSize = 0; - // Consider modules with the "hw.techlib.info" attribute as library + // Consider modules with the "synth.mapping_cost" attribute as library // modules. - // TODO: This attribute should be replaced with a more structured - // representation of technology library information. Specifically, we should - // have a dedicated operation for technology library. SmallVector nonLibraryModules; for (auto hwModule : module.getOps()) { - auto techInfo = - hwModule->getAttrOfType("hw.techlib.info"); - if (!techInfo) { - // If the module does not have the techlib info, it is not a library - // TODO: Run mapping only when the module is under the specific - // hierarchy. + + auto mappingCost = + hwModule->getAttrOfType("synth.mapping_cost"); + if (!mappingCost) { nonLibraryModules.push_back(hwModule); continue; } - // Get area and delay attributes - auto areaAttr = techInfo.getAs("area"); - auto delayAttr = techInfo.getAs("delay"); - if (!areaAttr || !delayAttr) { - mlir::emitError(hwModule.getLoc()) - << "Library module " << hwModule.getModuleName() - << " must have 'area'(float) and 'delay' (2d array to represent " - "input-output pair delay) attributes"; + double area = mappingCost.getArea().getValue().convertToDouble(); + + StringAttr outputName; + hw::ModulePortInfo ports(hwModule.getPortList()); + for (const auto &port : ports.getOutputs()) { + if (outputName) { + hwModule.emitError( + "Modules with multiple outputs are not supported yet"); + signalPassFailure(); + return; + } + outputName = port.name; + } + if (!outputName) { + hwModule.emitError("expected library module to have an output"); signalPassFailure(); return; } - double area = areaAttr.getValue().convertToDouble(); + llvm::DenseMap delayByInput; + for (auto attr : mappingCost.getArcs()) { + auto arc = cast(attr); + if (!arc) { + hwModule.emitError( + "expected synth.linear_timing_arc in synth.mapping_cost arcs"); + signalPassFailure(); + return; + } + + if (arc.getPin() != outputName) { + hwModule.emitError("mapping cost arc output '") + << arc.getPin().getValue() << "' does not match module output '" + << outputName.getValue() << "'"; + signalPassFailure(); + return; + } + + int64_t intrinsicDelay = arc.getIntrinsic(); + + // TechMapper currently preserves the old integer per-pin delay model. + // The sensitivity, polarity, and input capacitance fields are carried + // in the attribute for future load-aware mapping. + if (!delayByInput + .try_emplace(arc.getRelatedPin(), + static_cast(intrinsicDelay)) + .second) { + hwModule.emitError("duplicate mapping cost arc for input '") + << arc.getRelatedPin().getValue() << "'"; + signalPassFailure(); + return; + } + } SmallVector delay; - for (auto delayValue : delayAttr) { - auto delayArray = cast(delayValue); - for (auto delayElement : delayArray) { - // FIXME: Currently we assume delay is given as integer attributes, - // this should be replaced once we have a proper cell op with - // dedicated timing attributes with units. - delay.push_back( - cast(delayElement).getValue().getZExtValue()); + for (const auto &port : hwModule.getPortList()) { + if (!port.isInput()) + continue; + + auto it = delayByInput.find(port.name); + if (it == delayByInput.end()) { + hwModule.emitError("missing mapping cost arc for input '") + << port.name.getValue() << "'"; + signalPassFailure(); + return; } + + delay.push_back(it->second); + } + + if (delay.size() != delayByInput.size()) { + hwModule.emitError( + "synth.mapping_cost arcs do not match module inputs"); + signalPassFailure(); + return; } + // Compute NPN Class for the module. auto npnClass = getNPNClassFromModule(hwModule); if (failed(npnClass)) { diff --git a/test/Dialect/Synth/tech-mapper-error.mlir b/test/Dialect/Synth/tech-mapper-error.mlir index 60cbc99a2dca..f29de2581f2e 100644 --- a/test/Dialect/Synth/tech-mapper-error.mlir +++ b/test/Dialect/Synth/tech-mapper-error.mlir @@ -1,6 +1,6 @@ // RUN: circt-opt --pass-pipeline='builtin.module(synth-tech-mapper)' %s --split-input-file --verify-diagnostics -hw.module @do_nothing(in %a : i1, out result : i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[1]]}} { +hw.module @do_nothing(in %a : i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>], input_caps = {}>} { hw.output %a : i1 } @@ -13,7 +13,7 @@ hw.module @test(in %a : i1, in %b : i1, out result : i1) { // ----- // expected-error@+1 {{Modules with multiple outputs are not supported yet}} -hw.module @multi_output(in %a : i1, out result1 : i1, out result2 : i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[1], [1]]}} { +hw.module @multi_output(in %a : i1, out result1 : i1, out result2 : i1) attributes {synth.mapping_cost = #synth.mapping_cost>], input_caps = {}>} { hw.output %a, %a : i1, i1 } @@ -25,7 +25,7 @@ hw.module @test(in %a : i1, out result : i1) { // ----- // expected-error@+1 {{All input ports must be single bit}} -hw.module @multibit(in %a : i2, in %b: i1, out result : i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[1], [2]]}} { +hw.module @multibit(in %a : i2, in %b: i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 2, 0, #synth.polarity>], input_caps = {}>} { hw.output %b: i1 } @@ -33,7 +33,7 @@ hw.module @multibit(in %a : i2, in %b: i1, out result : i1) attributes {hw.techl // expected-error@+1 {{All output ports must be single bit}} -hw.module @multibit(in %a : i1, in %b: i1, out result : i2) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[1], [2]]}} { +hw.module @multibit(in %a : i1, in %b: i1, out result : i2) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 2, 0, #synth.polarity>], input_caps = {}>} { %0 = comb.concat %a, %b : i1, i1 hw.output %0: i2 } @@ -41,7 +41,7 @@ hw.module @multibit(in %a : i1, in %b: i1, out result : i2) attributes {hw.techl // ----- -hw.module @multibit(in %a : i1, in %b: i1, out result : i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[1], [2]]}} { +hw.module @multibit(in %a : i1, in %b: i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 2, 0, #synth.polarity>], input_caps = {}>} { // expected-error@+1 {{Unsupported operation for truth table simulation}} %0 = hw.constant 1 : i2 %1 = comb.extract %0 from 1 : (i2) -> i1 @@ -51,7 +51,7 @@ hw.module @multibit(in %a : i1, in %b: i1, out result : i1) attributes {hw.techl // ----- -hw.module @multibit(in %a : i1, in %b: i1, out result : i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[1], [2]]}} { +hw.module @multibit(in %a : i1, in %b: i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 2, 0, #synth.polarity>], input_caps = {}>} { // expected-error@+1 {{Unsupported operation for truth table simulation}} %0 = comb.add %a, %b : i1 hw.output %0: i1 @@ -64,11 +64,38 @@ hw.module @too_many_input_bits(in %a0 : i1, in %a1 : i1, in %a2 : i1, in %a3 : i in %a5 : i1, in %a6 : i1, in %a7 : i1, in %a8 : i1, in %a9 : i1, in %a10 : i1, in %a11 : i1, in %a12 : i1, in %a13 : i1, in %a14 : i1, in %a15 : i1, in %a16 : i1, out result : i1) - attributes {hw.techlib.info = { - area = 1.0 : f64, - delay = [[1], [1], [1], [1], [1], [1], [1], [1], [1], [1], - [1], [1], [1], [1], [1], [1], [1]] - }} { + attributes {synth.mapping_cost = #synth.mapping_cost>, + #synth.linear_timing_arc<"result", "a1", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a2", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a3", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a4", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a5", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a6", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a7", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a8", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a9", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a10", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a11", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a12", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a13", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a14", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a15", 1, 0, #synth.polarity>, + #synth.linear_timing_arc<"result", "a16", 1, 0, #synth.polarity> + ], input_caps = {}>} { %0 = synth.aig.and_inv %a0, %a1 : i1 hw.output %0: i1 } + +// ----- + +// expected-error@+1 {{duplicate mapping cost arc for input 'a'}} +hw.module @duplicate_arc(in %a : i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "a", 2, 0, #synth.polarity>], input_caps = {}>} { + hw.output %a : i1 +} + +// ----- + +// expected-error@+1 {{expected library module to have an output}} +hw.module @no_output() attributes {synth.mapping_cost = #synth.mapping_cost} { +} diff --git a/test/Dialect/Synth/tech-mapper.mlir b/test/Dialect/Synth/tech-mapper.mlir index 1bde0ab546b0..2f1019effd89 100644 --- a/test/Dialect/Synth/tech-mapper.mlir +++ b/test/Dialect/Synth/tech-mapper.mlir @@ -1,26 +1,26 @@ // RUN: circt-opt --pass-pipeline='builtin.module(synth-tech-mapper{strategy=area test=true max-cuts-per-root=8})' %s | FileCheck %s --check-prefixes CHECK,AREA // RUN: circt-opt --pass-pipeline='builtin.module(synth-tech-mapper{strategy=timing test=true max-cuts-per-root=8})' %s | FileCheck %s --check-prefixes CHECK,TIMING -hw.module @and_inv(in %a : i1, in %b : i1, out result : i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[1], [1]]}} { +hw.module @and_inv(in %a : i1, in %b : i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 1, 0, #synth.polarity>], input_caps = {}>} { %false = hw.constant false %true = hw.constant true %0 = synth.aig.and_inv %a, %b, not %false, %true : i1 hw.output %0 : i1 } -hw.module @and_inv_n(in %a : i1, in %b : i1, out result : i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[1], [1]]}} { +hw.module @and_inv_n(in %a : i1, in %b : i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 1, 0, #synth.polarity>], input_caps = {}>} { %0 = synth.aig.and_inv not %a, %b : i1 hw.output %0 : i1 } -hw.module @and_inv_nn(in %a : i1, in %b : i1, out result : i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[1], [1]]}} { +hw.module @and_inv_nn(in %a : i1, in %b : i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 1, 0, #synth.polarity>], input_caps = {}>} { %0 = synth.aig.and_inv not %a, not %b : i1 hw.output %0 : i1 } // Delay is shorter than @and_inv + @and_inv_n_n. Area is (significantly) larger than @and_inv_n + @and_inv_n_n. // Check that we use @and_inv_3 if strategy = timing, and @and_inv_n + @and_inv_n_n if strategy = area. -hw.module @and_inv_3(in %a : i1, in %b : i1, in %c : i1, out result : i1) attributes {hw.techlib.info = {area = 10.0 : f64, delay = [[1], [1], [1]]}} { +hw.module @and_inv_3(in %a : i1, in %b : i1, in %c : i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 1, 0, #synth.polarity>, #synth.linear_timing_arc<"result", "c", 1, 0, #synth.polarity>], input_caps = {}>} { %0 = synth.aig.and_inv %a, %b : i1 %1 = synth.aig.and_inv not %0, %c : i1 hw.output %1 : i1 @@ -38,7 +38,7 @@ hw.module @test_strategy(in %a : i1, in %b : i1, in %c : i1, out result : i1) { hw.output %1 : i1 } -hw.module @permutation(in %a: i1, in %b: i1, in %c: i1, in %d: i1, out result: i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[1], [1], [1], [1]]}} { +hw.module @permutation(in %a: i1, in %b: i1, in %c: i1, in %d: i1, out result: i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 1, 0, #synth.polarity>, #synth.linear_timing_arc<"result", "c", 1, 0, #synth.polarity>, #synth.linear_timing_arc<"result", "d", 1, 0, #synth.polarity>], input_caps = {}>} { %0 = synth.aig.and_inv %a, not %b : i1 %1 = synth.aig.and_inv %c, not %d : i1 %2 = synth.aig.and_inv %0, not %1 : i1 @@ -54,7 +54,7 @@ hw.module @permutation_test(in %p: i1, in %q: i1, in %r: i1, in %s: i1, out resu hw.output %2 : i1 } -hw.module @and_inv_5(in %a : i1, in %b : i1, in %c : i1, in %d : i1, in %e: i1, out result : i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[1], [2], [2], [2], [1]]}} { +hw.module @and_inv_5(in %a : i1, in %b : i1, in %c : i1, in %d : i1, in %e: i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 2, 0, #synth.polarity>, #synth.linear_timing_arc<"result", "c", 2, 0, #synth.polarity>, #synth.linear_timing_arc<"result", "d", 2, 0, #synth.polarity>, #synth.linear_timing_arc<"result", "e", 1, 0, #synth.polarity>], input_caps = {}>} { %0 = synth.aig.and_inv not %a, %b, not %c, %d, not %e : i1 hw.output %0 : i1 } @@ -77,7 +77,7 @@ hw.module @and_inv_5_test(in %a : i1, in %b : i1, in %c : i1, in %d : i1, in %e: // CHECK-NEXT: hw.output %[[result_0]], %[[result_1]] : i1, i1 } -hw.module @area_flow(in %a : i1, in %b : i1, in %c: i1, out result : i1) attributes {hw.techlib.info = {area = 1.5 : f64, delay = [[10], [10], [10], [10], [10]]}} { +hw.module @area_flow(in %a : i1, in %b : i1, in %c: i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "b", 10, 0, #synth.polarity>, #synth.linear_timing_arc<"result", "c", 10, 0, #synth.polarity>], input_caps = {}>} { %0 = synth.aig.and_inv not %a, not %b : i1 %1 = synth.aig.and_inv not %c, %0 : i1 hw.output %1 : i1 @@ -163,7 +163,7 @@ hw.module @extract_concat_test(in %data : i4, in %ctrl : i2, out result : i3) { hw.output %result_concat : i3 } -hw.module @dot_lib(in %x : i1, in %y : i1, in %z : i1, out result : i1) attributes {hw.techlib.info = {area = 1.0 : f64, delay = [[1], [1], [1]]}} { +hw.module @dot_lib(in %x : i1, in %y : i1, in %z : i1, out result : i1) attributes {synth.mapping_cost = #synth.mapping_cost>, #synth.linear_timing_arc<"result", "y", 1, 0, #synth.polarity>, #synth.linear_timing_arc<"result", "z", 1, 0, #synth.polarity>], input_caps = {}>} { %0 = synth.dot %z, not %x, not %y : i1 hw.output %0 : i1 } @@ -176,3 +176,4 @@ hw.module @dot_test(in %x : i1, in %y : i1, in %z : i1, out result : i1) { %0 = synth.dot %x, not %y, not %z : i1 hw.output %0 : i1 } +