accelforge 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- accelforge/__init__.py +21 -0
- accelforge/_accelerated_imports.py +16 -0
- accelforge/_deprecate/_simanneal/evalmapping.py +271 -0
- accelforge/_deprecate/_simanneal/mapspaceglobals.py +298 -0
- accelforge/_deprecate/_simanneal/simanneal.py +666 -0
- accelforge/_deprecate/_simanneal/tracking.py +105 -0
- accelforge/_deprecate/_simanneal/wrappers.py +218 -0
- accelforge/_deprecate/_simanneal2/__init__.py +7 -0
- accelforge/_deprecate/_simanneal2/simanneal.py +493 -0
- accelforge/_deprecate/_simanneal2/tracking.py +116 -0
- accelforge/_deprecate/compatibility_util.py +181 -0
- accelforge/_deprecate/layerdeduplication/__init__.py +2 -0
- accelforge/_deprecate/layerdeduplication/group_similar_einsums.py +160 -0
- accelforge/_deprecate/layerdeduplication/grouped_einsums.py +84 -0
- accelforge/_deprecate/mapping_filter_tags/__init__.py +2 -0
- accelforge/_deprecate/mapping_filter_tags/ffmt.py +212 -0
- accelforge/_deprecate/mapping_filter_tags/onesplit.py +24 -0
- accelforge/_deprecate/mapping_filter_tags/util.py +24 -0
- accelforge/_deprecate/tags.py +69 -0
- accelforge/_deprecate/viz/__init__.py +0 -0
- accelforge/_deprecate/viz/interactive.py +159 -0
- accelforge/_deprecate/viz/reservationtree.py +307 -0
- accelforge/_deprecate/viz/ski_slope.py +88 -0
- accelforge/_version.py +15 -0
- accelforge/examples.py +39 -0
- accelforge/frontend/__init__.py +10 -0
- accelforge/frontend/_binding.py +129 -0
- accelforge/frontend/_workload_isl/__init__.py +2 -0
- accelforge/frontend/_workload_isl/_isl.py +149 -0
- accelforge/frontend/_workload_isl/_symbolic.py +141 -0
- accelforge/frontend/arch copy.py +1544 -0
- accelforge/frontend/arch.py +1642 -0
- accelforge/frontend/config.py +63 -0
- accelforge/frontend/mapper/__init__.py +5 -0
- accelforge/frontend/mapper/ffm.py +126 -0
- accelforge/frontend/mapper/mapper.py +7 -0
- accelforge/frontend/mapper/metrics.py +30 -0
- accelforge/frontend/mapping/__init__.py +1 -0
- accelforge/frontend/mapping/mapping.py +1736 -0
- accelforge/frontend/model.py +14 -0
- accelforge/frontend/renames.py +150 -0
- accelforge/frontend/spec copy.py +230 -0
- accelforge/frontend/spec.py +301 -0
- accelforge/frontend/variables.py +12 -0
- accelforge/frontend/workload.py +952 -0
- accelforge/mapper/FFM/__init__.py +9 -0
- accelforge/mapper/FFM/_join_pmappings/__init__.py +0 -0
- accelforge/mapper/FFM/_join_pmappings/compatibility.py +653 -0
- accelforge/mapper/FFM/_join_pmappings/compress_pmappings.py +140 -0
- accelforge/mapper/FFM/_join_pmappings/join_pmappings.py +703 -0
- accelforge/mapper/FFM/_join_pmappings/pmapping_dataframe.py +901 -0
- accelforge/mapper/FFM/_join_pmappings/pmapping_group.py +337 -0
- accelforge/mapper/FFM/_make_pmappings/contraints/__init__.py +0 -0
- accelforge/mapper/FFM/_make_pmappings/contraints/constraints.py +360 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmapping_templates/__init__.py +1 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmapping_templates/make_loops.py +373 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmapping_templates/make_pmapping_templates.py +463 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmapping_templates/make_reservations.py +95 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmapping_templates/make_storage_order.py +382 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmapping_templates/make_storages.py +155 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmappings.py +411 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmappings_from_templates/__init__.py +1 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmappings_from_templates/make_pmappings_from_templates.py +407 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmappings_from_templates/make_tile_shapes.py +1681 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmappings_from_templates/run_model.py +170 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmappings_from_templates/symbol_relations.py +174 -0
- accelforge/mapper/FFM/_make_pmappings/pmapper_job.py +282 -0
- accelforge/mapper/FFM/_pareto_df/df_convention.py +273 -0
- accelforge/mapper/FFM/_pareto_df/pareto copy.py +836 -0
- accelforge/mapper/FFM/_pareto_df/pareto.py +508 -0
- accelforge/mapper/FFM/data.py +61 -0
- accelforge/mapper/FFM/main copy.py +236 -0
- accelforge/mapper/FFM/main.py +208 -0
- accelforge/mapper/FFM/mappings.py +510 -0
- accelforge/mapper/FFM/pmappings.py +310 -0
- accelforge/mapper/__init__.py +4 -0
- accelforge/mapper.py +0 -0
- accelforge/model/__init__.py +1 -0
- accelforge/model/_looptree/__init__.py +0 -0
- accelforge/model/_looptree/accesses.py +335 -0
- accelforge/model/_looptree/capacity/__init__.py +1 -0
- accelforge/model/_looptree/capacity/aggregators.py +36 -0
- accelforge/model/_looptree/capacity/capacity.py +47 -0
- accelforge/model/_looptree/energy.py +150 -0
- accelforge/model/_looptree/equivalent_ranks.py +29 -0
- accelforge/model/_looptree/latency/__init__.py +1 -0
- accelforge/model/_looptree/latency/latency.py +98 -0
- accelforge/model/_looptree/latency/memory.py +120 -0
- accelforge/model/_looptree/latency/processors.py +92 -0
- accelforge/model/_looptree/mapping_utilities.py +71 -0
- accelforge/model/_looptree/reuse/__init__.py +4 -0
- accelforge/model/_looptree/reuse/isl/__init__.py +1 -0
- accelforge/model/_looptree/reuse/isl/des.py +59 -0
- accelforge/model/_looptree/reuse/isl/isl_functions.py +374 -0
- accelforge/model/_looptree/reuse/isl/mapping_to_isl/__init__.py +4 -0
- accelforge/model/_looptree/reuse/isl/mapping_to_isl/analyze_mapping.py +297 -0
- accelforge/model/_looptree/reuse/isl/mapping_to_isl/skews_from_mapping.py +236 -0
- accelforge/model/_looptree/reuse/isl/mapping_to_isl/tiling.py +685 -0
- accelforge/model/_looptree/reuse/isl/mapping_to_isl/types.py +188 -0
- accelforge/model/_looptree/reuse/isl/spatial.py +260 -0
- accelforge/model/_looptree/reuse/isl/temporal.py +182 -0
- accelforge/model/_looptree/reuse/symbolic/__init__.py +1 -0
- accelforge/model/_looptree/reuse/symbolic/symbolic copy 2.py +1346 -0
- accelforge/model/_looptree/reuse/symbolic/symbolic copy.py +1408 -0
- accelforge/model/_looptree/reuse/symbolic/symbolic.py +1396 -0
- accelforge/model/_looptree/run.py +122 -0
- accelforge/model/_looptree/types.py +26 -0
- accelforge/model/_looptree/visualization/__init__.py +0 -0
- accelforge/model/_looptree/visualization/occupancy.py +11 -0
- accelforge/model/main.py +222 -0
- accelforge/plotting/__init__.py +2 -0
- accelforge/plotting/mappings.py +219 -0
- accelforge/plotting/specs.py +57 -0
- accelforge/util/__init__.py +4 -0
- accelforge/util/_base_analysis_types.py +24 -0
- accelforge/util/_basetypes.py +1089 -0
- accelforge/util/_frozenset.py +36 -0
- accelforge/util/_isl.py +29 -0
- accelforge/util/_itertools.py +14 -0
- accelforge/util/_mathfuncs.py +57 -0
- accelforge/util/_parse_expressions.py +339 -0
- accelforge/util/_picklecache.py +32 -0
- accelforge/util/_setexpressions.py +268 -0
- accelforge/util/_sympy/__init__.py +0 -0
- accelforge/util/_sympy/broadcast_max.py +18 -0
- accelforge/util/_visualization.py +112 -0
- accelforge/util/_yaml.py +579 -0
- accelforge/util/parallel.py +193 -0
- accelforge-0.0.1.dist-info/METADATA +64 -0
- accelforge-0.0.1.dist-info/RECORD +258 -0
- accelforge-0.0.1.dist-info/WHEEL +5 -0
- accelforge-0.0.1.dist-info/licenses/LICENSE +19 -0
- accelforge-0.0.1.dist-info/top_level.txt +5 -0
- docs/_build/html/_sources/fastfusion.frontend.mapper.rst.txt +37 -0
- docs/_build/html/_sources/fastfusion.frontend.rst.txt +70 -0
- docs/_build/html/_sources/fastfusion.frontend.workload.rst.txt +21 -0
- docs/_build/html/_sources/fastfusion.mapper.FFM.rst.txt +37 -0
- docs/_build/html/_sources/fastfusion.mapper.rst.txt +18 -0
- docs/_build/html/_sources/fastfusion.rst.txt +20 -0
- docs/_build/html/_sources/fastfusion.util.rst.txt +21 -0
- docs/_build/html/_sources/index.rst.txt +87 -0
- docs/_build/html/_sources/modules.rst.txt +7 -0
- docs/_build/html/_sources/notes/citation.rst.txt +45 -0
- docs/_build/html/_sources/notes/definitions.rst.txt +43 -0
- docs/_build/html/_sources/notes/faqs.rst.txt +39 -0
- docs/_build/html/_sources/notes/modeling/accelerator_energy_latency.rst.txt +72 -0
- docs/_build/html/_sources/notes/modeling/component_energy_area.rst.txt +96 -0
- docs/_build/html/_sources/notes/modeling/mapping.rst.txt +100 -0
- docs/_build/html/_sources/notes/modeling.rst.txt +33 -0
- docs/_build/html/_sources/notes/parsing/arithmetic_parsing.rst.txt +136 -0
- docs/_build/html/_sources/notes/parsing/setexpressions.rst.txt +63 -0
- docs/_build/html/_sources/notes/parsing/yaml_parsing.rst.txt +176 -0
- docs/_build/html/_sources/notes/quickstart_and_installation.rst.txt +9 -0
- docs/_build/html/_sources/notes/spec/architecture.rst.txt +133 -0
- docs/_build/html/_sources/notes/spec/mapping.rst.txt +12 -0
- docs/_build/html/_sources/notes/spec/workload.rst.txt +83 -0
- docs/_build/html/_sources/notes/spec.rst.txt +36 -0
- docs/source/_ext/include_attrs.py +213 -0
- docs/source/_ext/include_docstring.py +364 -0
- docs/source/_ext/include_functions.py +154 -0
- docs/source/_ext/include_notebook.py +131 -0
- docs/source/_ext/include_yaml.py +119 -0
- docs/source/_ext/inherited_attributes.py +222 -0
- docs/source/_ext/paths.py +4 -0
- docs/source/conf.py +79 -0
- examples/arches/compute_in_memory/_include.yaml +74 -0
- examples/arches/compute_in_memory/_include_functions.py +229 -0
- examples/arches/compute_in_memory/_load_spec.py +57 -0
- examples/arches/compute_in_memory/components/c2c_multiplier.py +181 -0
- examples/arches/compute_in_memory/components/dac_c2c_r2r.py +605 -0
- examples/arches/compute_in_memory/components/misc.py +195 -0
- examples/arches/compute_in_memory/components/util/bit_functions.py +51 -0
- examples/arches/compute_in_memory/components/zero_comparator.py +92 -0
- examples/arches/compute_in_memory/isaac.yaml +233 -0
- examples/arches/compute_in_memory/memory_cells/ecram_demo.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/rram_example.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/rram_isaac_isca_2016.yaml +64 -0
- examples/arches/compute_in_memory/memory_cells/rram_neurosim_default.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/rram_raella_isca_2023.yaml +70 -0
- examples/arches/compute_in_memory/memory_cells/rram_wan_nature_2022.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/sram_colonnade_jssc_2021.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/sram_example.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/sram_jia_jssc_2020.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/sram_sinangil_jssc_2021.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/sram_wang_vlsi_2022.yaml +63 -0
- examples/arches/compute_in_memory/wang_vlsi_2022.yaml +289 -0
- examples/arches/eyeriss.yaml +68 -0
- examples/arches/fanout_variations/at_glb.yaml +31 -0
- examples/arches/fanout_variations/at_glb_with_fanout_node.yaml +34 -0
- examples/arches/fanout_variations/at_mac.yaml +31 -0
- examples/arches/fanout_variations/at_mac_with_constraints.yaml +38 -0
- examples/arches/fanout_variations/at_mac_with_fanout_node.yaml +34 -0
- examples/arches/nvdla.yaml +47 -0
- examples/arches/simple.yaml +28 -0
- examples/arches/tpu_v4i.yaml +67 -0
- examples/mappings/unfused_matmuls_to_simple.yaml +33 -0
- examples/misc/component_annotated.yaml +33 -0
- examples/workloads/gpt3_6.7B.yaml +124 -0
- examples/workloads/matmuls.yaml +20 -0
- examples/workloads/mobilenet_28.yaml +81 -0
- examples/workloads/mobilenet_various_separate.yaml +106 -0
- examples/workloads/three_matmuls_annotated.yaml +59 -0
- notebooks/.ipynb_checkpoints/fastfusion_arch_study_michael-checkpoint.ipynb +359 -0
- notebooks/compute_in_memory/_scripts.py +339 -0
- notebooks/compute_in_memory/isaac.guide.ipynb +270 -0
- notebooks/compute_in_memory/wang_vlsi_2022.ipynb +602 -0
- notebooks/paths.py +4 -0
- notebooks/tutorials/.ipynb_checkpoints/1_FFM-checkpoint.ipynb +3110 -0
- notebooks/tutorials/FFM.ipynb +3498 -0
- notebooks/tutorials/_include.py +48 -0
- notebooks/tutorials/component_energy_area.ipynb +363 -0
- tests/Q_mapping.yaml +38 -0
- tests/__init__.py +0 -0
- tests/conv.mapping.yaml +27 -0
- tests/conv.workload.yaml +13 -0
- tests/conv_sym.mapping.yaml +43 -0
- tests/copy.mapping.yaml +35 -0
- tests/copy.workload.yaml +15 -0
- tests/distribuffers/__init__.py +0 -0
- tests/distribuffers/multicast/test_cases.yaml +482 -0
- tests/distribuffers/spec/binding/valid_bindings.yaml +97 -0
- tests/distribuffers/spec/distributed.yaml +100 -0
- tests/distribuffers/spec/logical_arch.yaml +32 -0
- tests/distribuffers/spec/physical_arch.yaml +69 -0
- tests/distribuffers/test_binding.py +48 -0
- tests/frontend/__init__.py +0 -0
- tests/frontend/test_mapping_viz.py +52 -0
- tests/mapper/__init__.py +0 -0
- tests/mapper/configs/conv1d/conv1d.mapping.yaml +31 -0
- tests/mapper/configs/conv1d/conv1d.workload.yaml +11 -0
- tests/mapper/configs/two_conv1d/two_conv1d.expected.yaml +38 -0
- tests/mapper/configs/two_conv1d/two_conv1d.mapping.yaml +54 -0
- tests/mapper/configs/two_conv1d/two_conv1d.workload.yaml +19 -0
- tests/mapper/test_mapping_to_isl.py +90 -0
- tests/mapper/test_spatial_reuse_analysis.py +67 -0
- tests/mapper/test_temporal_reuse_analysis.py +56 -0
- tests/mapper/util.py +58 -0
- tests/matmul.mapping.yaml +29 -0
- tests/matmul.workload.yaml +12 -0
- tests/matmul_spatial.mapping.yaml +44 -0
- tests/mha.renames.yaml +65 -0
- tests/mha.workload.yaml +67 -0
- tests/mha.yaml +59 -0
- tests/mha_full.workload.yaml +67 -0
- tests/mobilenet.workload.yaml +35 -0
- tests/mobilenet_long.workload.yaml +64 -0
- tests/pmappingcache.py +24 -0
- tests/processing_stage.arch.yaml +40 -0
- tests/snowcat.arch.yaml +36 -0
- tests/test_ffm_join_pmappings.py +106 -0
- tests/test_ffm_make_pmappings.py +82 -0
- tests/test_ffm_make_tile_shapes.py +49 -0
- tests/test_mapper.py +100 -0
- tests/test_model.py +37 -0
- tests/test_plotting.py +72 -0
- tests/test_processing_stage.py +46 -0
- tests/test_symbolic_model.py +248 -0
- tests/test_workload.py +141 -0
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
from hwcomponents.scaling import linear
|
|
4
|
+
from hwcomponents_neurosim import FlipFlop
|
|
5
|
+
from misc import Capacitor
|
|
6
|
+
from typing import List
|
|
7
|
+
|
|
8
|
+
from hwcomponents import ComponentModel, action
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def value2bits(value: int, resolution: int) -> List[int]:
|
|
12
|
+
"""Converts a value to a list of bits."""
|
|
13
|
+
return [int(i) for i in bin(value)[2:].zfill(resolution)]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class _X2XLadderDAC(ComponentModel):
|
|
17
|
+
"""
|
|
18
|
+
Base class for X2X Ladder DACs. This class is not intended to be instantiated
|
|
19
|
+
directly. Use a subclass.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
priority = 0.5
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
resolution: int,
|
|
27
|
+
voltage: float,
|
|
28
|
+
unit_x: float,
|
|
29
|
+
tech_node: int,
|
|
30
|
+
area: float,
|
|
31
|
+
leak_power: float,
|
|
32
|
+
kind: str,
|
|
33
|
+
hist: List[float] = None,
|
|
34
|
+
load_resistance: float = 0,
|
|
35
|
+
load_capacitance: float = 0,
|
|
36
|
+
cycle_period: float = 1e-9,
|
|
37
|
+
):
|
|
38
|
+
self.resolution = resolution
|
|
39
|
+
self.voltage = voltage
|
|
40
|
+
self._unit_x = unit_x
|
|
41
|
+
self.tech_node = tech_node
|
|
42
|
+
self._max_value = 2**resolution - 1
|
|
43
|
+
self.hist = hist
|
|
44
|
+
self.load_resistance = load_resistance
|
|
45
|
+
self.load_capacitance = load_capacitance
|
|
46
|
+
self._kind = kind
|
|
47
|
+
self.cycle_period = cycle_period
|
|
48
|
+
self._output_cap = Capacitor(
|
|
49
|
+
voltage=voltage, capacitance=load_capacitance, tech_node=tech_node
|
|
50
|
+
)
|
|
51
|
+
self._flip_flops = FlipFlop(
|
|
52
|
+
tech_node=tech_node, cycle_period=cycle_period, n_bits=resolution
|
|
53
|
+
)
|
|
54
|
+
super().__init__(
|
|
55
|
+
area=self._flip_flops.area + area,
|
|
56
|
+
leak_power=self._flip_flops.leak_power + leak_power,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
def _get_latency(
|
|
60
|
+
self,
|
|
61
|
+
load_capacitance: float,
|
|
62
|
+
load_resistance: float,
|
|
63
|
+
lsbs_expected_to_change: float = None,
|
|
64
|
+
lsbs_allowed_incorrect: float = 0,
|
|
65
|
+
porp_charge_loss_to_overcome: float = 0,
|
|
66
|
+
) -> float:
|
|
67
|
+
"""
|
|
68
|
+
Returns the latency in seconds to convert the input value to an analog voltage
|
|
69
|
+
and charge a load. If the latency is greater than the cycle period, the DAC will
|
|
70
|
+
be run more slowly in order to meet the required hold time and settle to <=0.5
|
|
71
|
+
LSB error. If the latency is less than the cycle period, the DAC will hold the
|
|
72
|
+
value for the full cycle period, and may consume more power than necessary. Note
|
|
73
|
+
that hold time will be longer if load_capacitance is increased or
|
|
74
|
+
load_resistance is decreased.
|
|
75
|
+
|
|
76
|
+
Parameters
|
|
77
|
+
----------
|
|
78
|
+
load_capacitance: float
|
|
79
|
+
Load capacitance in Farads
|
|
80
|
+
load_resistance: float
|
|
81
|
+
Load resistance in Ohms
|
|
82
|
+
lsbs_expected_to_change: float, optional
|
|
83
|
+
Expected values. Lower values mean a lower-swing output. Defaults to None.
|
|
84
|
+
lsbs_allowed_incorrect: float, optional
|
|
85
|
+
Number of LSBs allowed to be incorrect in the final converted value.
|
|
86
|
+
Defaults to 0.
|
|
87
|
+
porp_charge_loss_to_overcome: float, optional
|
|
88
|
+
Porportion (0 to 1) of the charge on the load capacitor that is leaked
|
|
89
|
+
between cycles amd must be recharged. Defaults to 0.
|
|
90
|
+
|
|
91
|
+
Returns
|
|
92
|
+
-------
|
|
93
|
+
float: Latency in seconds
|
|
94
|
+
|
|
95
|
+
"""
|
|
96
|
+
# Instant convergence if there's no load resistance
|
|
97
|
+
if self.load_resistance + load_resistance == 0:
|
|
98
|
+
return self.cycle_period
|
|
99
|
+
|
|
100
|
+
if lsbs_expected_to_change is None:
|
|
101
|
+
lsbs_expected_to_change = self.resolution
|
|
102
|
+
|
|
103
|
+
lsbs_allowed_incorrect += 0.5
|
|
104
|
+
|
|
105
|
+
# Time it takes for the output to converge within lsb_error_allowed LSB
|
|
106
|
+
r = self.load_resistance + load_resistance
|
|
107
|
+
c = self.load_capacitance + load_capacitance
|
|
108
|
+
|
|
109
|
+
delta = 2**lsbs_expected_to_change / self._max_value
|
|
110
|
+
t0 = -math.log(delta + porp_charge_loss_to_overcome) * r * c
|
|
111
|
+
t1 = -math.log(2**lsbs_allowed_incorrect / self._max_value) * r * c
|
|
112
|
+
|
|
113
|
+
hold_time = t1 - t0
|
|
114
|
+
if hold_time > self.cycle_period:
|
|
115
|
+
self.logger.warning(
|
|
116
|
+
f"Required hold time {hold_time} is greater than the cycle period "
|
|
117
|
+
f"{self.cycle_period}. DAC will be run more slowly in order to meet "
|
|
118
|
+
f"the required hold time and settle to <=0.5 LSB error. Note that hold "
|
|
119
|
+
f"time will be longer if load_capacitance is increased or "
|
|
120
|
+
f"load_resistance is decreased."
|
|
121
|
+
)
|
|
122
|
+
if hold_time < self.cycle_period:
|
|
123
|
+
self.logger.warning(
|
|
124
|
+
f"Cycle period {self.cycle_period} is greater than the required hold "
|
|
125
|
+
f"time {hold_time}. DAC will hold the value for the full cycle period, "
|
|
126
|
+
f"and may therefore consume more power than necessary. Note that hold "
|
|
127
|
+
f"time will be longer if load_capacitance is increased or "
|
|
128
|
+
f"load_resistance is decreased."
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
return max(hold_time, self.cycle_period)
|
|
132
|
+
|
|
133
|
+
def solve_for_voltage_at_each_node(self, input_value: int) -> list:
|
|
134
|
+
"""
|
|
135
|
+
Solves the matrix:
|
|
136
|
+
[ 4 -2 0.... ][V_0]
|
|
137
|
+
input_voltages = [-2 5 -2 0 ..... ][V_1]
|
|
138
|
+
[ 0 -2 5 -2 0 .... ][V_2]
|
|
139
|
+
[ 0 0 -2 5 -2 0 ....][V_3]
|
|
140
|
+
[ ................... ][V_4]
|
|
141
|
+
[ 0 0 0 0 0 -2 3][V_{n-1}]
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
This matrix arises in C-2C and R-2R ladders. To solve, we set up the equation
|
|
145
|
+
for each node: 0 = (V_{i} - V_{i-1}) + (V_{i} - V_{i+1}) + (V_{i} - Input_{i}) /
|
|
146
|
+
2 The first node has an additional connector, and the last node does not
|
|
147
|
+
|
|
148
|
+
Parameters
|
|
149
|
+
----------
|
|
150
|
+
input_value: int
|
|
151
|
+
Input value to be converted. Must be between 0 and 2^resolution - 1.
|
|
152
|
+
|
|
153
|
+
Returns
|
|
154
|
+
-------
|
|
155
|
+
list[float]:
|
|
156
|
+
The voltage at each node in the ladder. The first element is the voltage at
|
|
157
|
+
the voltage farthest from the output, and the last element is the voltage
|
|
158
|
+
immediately before the output.
|
|
159
|
+
"""
|
|
160
|
+
# Reverse input_value_bits to get the MSB on the right side of the circuit,
|
|
161
|
+
# closest to the output
|
|
162
|
+
input_value_bits = value2bits(input_value, self.resolution)[::-1]
|
|
163
|
+
|
|
164
|
+
lhs = [i * self.voltage for i in input_value_bits]
|
|
165
|
+
matrix_values = [[0, 4, -2]]
|
|
166
|
+
for i in range(len(lhs) - 2):
|
|
167
|
+
matrix_values.append([-2, 5, -2])
|
|
168
|
+
matrix_values.append([-2, 3, 0])
|
|
169
|
+
|
|
170
|
+
for i in range(len(lhs) - 2, -1, -1):
|
|
171
|
+
mult = matrix_values[i][2] / matrix_values[i + 1][1]
|
|
172
|
+
matrix_values[i][1] -= matrix_values[i + 1][0] * mult
|
|
173
|
+
matrix_values[i][2] -= matrix_values[i + 1][1] * mult
|
|
174
|
+
lhs[i] -= lhs[i + 1] * mult
|
|
175
|
+
lhs[i] /= matrix_values[i][1]
|
|
176
|
+
matrix_values[i] = [j / matrix_values[i][1] for j in matrix_values[i]]
|
|
177
|
+
|
|
178
|
+
for i in range(0, len(lhs) - 1):
|
|
179
|
+
mult = matrix_values[i + 1][0] / matrix_values[i][1]
|
|
180
|
+
matrix_values[i + 1][0] -= matrix_values[i][1] * mult
|
|
181
|
+
matrix_values[i + 1][1] -= matrix_values[i][2] * mult
|
|
182
|
+
lhs[i + 1] -= lhs[i] * mult
|
|
183
|
+
|
|
184
|
+
lhs = [l / matrix_values[i][1] for i, l in enumerate(lhs)]
|
|
185
|
+
|
|
186
|
+
# Un-reverse the bits
|
|
187
|
+
return lhs[::-1]
|
|
188
|
+
|
|
189
|
+
def _input_value_to_analog_energy_or_power(self, input_value: int) -> float:
|
|
190
|
+
"""
|
|
191
|
+
Returns the energy or power to convert the input value to an analog voltage,
|
|
192
|
+
depending on whether unit_x is a capacitance or a resistance.
|
|
193
|
+
|
|
194
|
+
Parameters
|
|
195
|
+
----------
|
|
196
|
+
input_value: int
|
|
197
|
+
Input value to be converted. Must be between 0 and 2^resolution - 1.
|
|
198
|
+
|
|
199
|
+
Returns
|
|
200
|
+
-------
|
|
201
|
+
float: Energy in Joules
|
|
202
|
+
"""
|
|
203
|
+
input_value_bits = value2bits(input_value, self.resolution)
|
|
204
|
+
node_voltages = self.solve_for_voltage_at_each_node(input_value)
|
|
205
|
+
current = 0
|
|
206
|
+
for i, bit in enumerate(input_value_bits):
|
|
207
|
+
current += (self.voltage - node_voltages[i]) * (bit != 0)
|
|
208
|
+
energy = current * self.voltage * self._unit_x
|
|
209
|
+
assert energy >= 0
|
|
210
|
+
return energy
|
|
211
|
+
|
|
212
|
+
def _convert_energy(
|
|
213
|
+
self,
|
|
214
|
+
latency: float | None = None,
|
|
215
|
+
):
|
|
216
|
+
"""
|
|
217
|
+
Returns the average energy and latency to convert the input value to an analog
|
|
218
|
+
voltage
|
|
219
|
+
|
|
220
|
+
Parameters
|
|
221
|
+
----------
|
|
222
|
+
latency: float | None, optional
|
|
223
|
+
If this is a resistive DAC, energy scales with the latency for which the
|
|
224
|
+
value is held. If no latency is given, energy is returned without scaling.
|
|
225
|
+
"""
|
|
226
|
+
energy = 0
|
|
227
|
+
|
|
228
|
+
# This code resizes the histogram into the full distribution of values
|
|
229
|
+
# that this DAC can produce. It also makes sure to map the 0
|
|
230
|
+
# probability exactly.
|
|
231
|
+
newhist = [0] * 2**self.resolution
|
|
232
|
+
idx0 = len(self.hist) // 2
|
|
233
|
+
new_idx0 = len(newhist) // 2
|
|
234
|
+
width_scale = len(self.hist) / len(newhist)
|
|
235
|
+
prunedhist = [i for i in self.hist]
|
|
236
|
+
for exact_maps in [(0, 0), (idx0, new_idx0)]:
|
|
237
|
+
newhist[exact_maps[1]] = prunedhist[exact_maps[0]] / min(width_scale, 1)
|
|
238
|
+
prunedhist[exact_maps[0]] = 0
|
|
239
|
+
|
|
240
|
+
for i in range(len(newhist)):
|
|
241
|
+
if i == new_idx0 or i == 0:
|
|
242
|
+
continue
|
|
243
|
+
loc = i / len(newhist) * (len(prunedhist) - 1)
|
|
244
|
+
if width_scale > 1:
|
|
245
|
+
start = math.floor(loc)
|
|
246
|
+
end = min(math.ceil(start + width_scale), len(prunedhist) - 1)
|
|
247
|
+
for j in range(start, end):
|
|
248
|
+
newhist[i] += prunedhist[j]
|
|
249
|
+
else:
|
|
250
|
+
porp = loc - math.floor(loc)
|
|
251
|
+
newhist[i] += prunedhist[math.floor(loc)] * (1 - porp)
|
|
252
|
+
newhist[i] += prunedhist[math.ceil(loc)] * porp
|
|
253
|
+
|
|
254
|
+
sum_newhist = sum(newhist)
|
|
255
|
+
newhist = [n / sum_newhist for n in newhist]
|
|
256
|
+
|
|
257
|
+
# Calculate the energy
|
|
258
|
+
for i, p in enumerate(newhist):
|
|
259
|
+
energy += self._input_value_to_analog_energy_or_power(i) * p
|
|
260
|
+
energy /= sum(newhist)
|
|
261
|
+
assert energy >= 0
|
|
262
|
+
|
|
263
|
+
# Latency not none ->
|
|
264
|
+
if self._kind == "R2R":
|
|
265
|
+
assert latency is not None
|
|
266
|
+
energy *= latency
|
|
267
|
+
|
|
268
|
+
# Output cap energy
|
|
269
|
+
cap_e, _ = self._output_cap.switch(newhist, zero_between_values=False)
|
|
270
|
+
self.logger.info(f"Output capacitance consumed {cap_e}J")
|
|
271
|
+
assert cap_e >= 0
|
|
272
|
+
|
|
273
|
+
# Flip flop energy
|
|
274
|
+
flip_flops_e, _ = self._flip_flops.read()
|
|
275
|
+
probabilities = [0] * self.resolution
|
|
276
|
+
for value, probability in enumerate(newhist):
|
|
277
|
+
bits = value2bits(value, self.resolution)
|
|
278
|
+
for i, b in enumerate(bits):
|
|
279
|
+
probabilities[i] += probability * b
|
|
280
|
+
lo2hi_probability = sum(p * (1 - p) for p in probabilities)
|
|
281
|
+
flip_flops_e *= lo2hi_probability
|
|
282
|
+
assert flip_flops_e >= 0
|
|
283
|
+
|
|
284
|
+
self.logger.info(f"Flip-flops consumed {flip_flops_e}J")
|
|
285
|
+
return energy + self._get_controller_energy() + cap_e + flip_flops_e
|
|
286
|
+
|
|
287
|
+
def _get_controller_energy(self):
|
|
288
|
+
# 0.08pJ/bit at 22nm 1.0V
|
|
289
|
+
return (self.voltage * self.tech_node) ** 2 * self.resolution * 8e-8
|
|
290
|
+
|
|
291
|
+
@action
|
|
292
|
+
def convert(self):
|
|
293
|
+
"""
|
|
294
|
+
Returns the energy and latency to convert the input value to an analog voltage.
|
|
295
|
+
|
|
296
|
+
Returns
|
|
297
|
+
-------
|
|
298
|
+
float: Energy in Joules float: Latency in seconds
|
|
299
|
+
"""
|
|
300
|
+
min_latency = self._get_latency(
|
|
301
|
+
load_capacitance=self.load_capacitance, load_resistance=self.load_resistance
|
|
302
|
+
)
|
|
303
|
+
energy = self._convert_energy(latency=min_latency)
|
|
304
|
+
controller_energy = self._get_controller_energy()
|
|
305
|
+
self.logger.info(
|
|
306
|
+
f"{self._kind} DAC consumes {energy}J over{min_latency} seconds. "
|
|
307
|
+
f"Resistors consume {energy - controller_energy}J, "
|
|
308
|
+
f"Controller energy: {controller_energy}J"
|
|
309
|
+
)
|
|
310
|
+
return energy, min_latency
|
|
311
|
+
|
|
312
|
+
@action
|
|
313
|
+
def read(self):
|
|
314
|
+
"""
|
|
315
|
+
Returns the energy and latency to convert the input value to an analog voltage.
|
|
316
|
+
|
|
317
|
+
Returns
|
|
318
|
+
-------
|
|
319
|
+
float: Energy in Joules float: Latency in seconds
|
|
320
|
+
"""
|
|
321
|
+
return self.convert()
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
class C2CLadderDAC(_X2XLadderDAC):
|
|
325
|
+
"""
|
|
326
|
+
C-2C ladder DAC.
|
|
327
|
+
|
|
328
|
+
R-2R ladder and C-2C ladder DACs model those described in the paper: A Charge Domain
|
|
329
|
+
SRAM Compute-in-Memory Macro With C-2C Ladder-Based 8b MAC Unit in 22-nm FinFET
|
|
330
|
+
Process for Edge Inference Wang, Hechen and Liu, Renzhi and Dorrance, Richard and
|
|
331
|
+
Dasalukunte, Deepak and Lake, Dan and Carlton, Brent 10.1109/JSSC.2022.3232601
|
|
332
|
+
|
|
333
|
+
Parameters
|
|
334
|
+
----------
|
|
335
|
+
resolution: int
|
|
336
|
+
The resolution of the DAC.
|
|
337
|
+
voltage: float
|
|
338
|
+
The voltage of the DAC.
|
|
339
|
+
unit_resistance: float
|
|
340
|
+
The unit resistance of the DAC.
|
|
341
|
+
tech_node: int
|
|
342
|
+
The tech node of the DAC.
|
|
343
|
+
cycle_period: float, optional
|
|
344
|
+
The cycle period of the clock driving the DAC, and also the minimum time the DAC
|
|
345
|
+
must hold any output values (longer if it takes longer to settle). Defaults to
|
|
346
|
+
1e-9.
|
|
347
|
+
hist: List[float], optional
|
|
348
|
+
The histogram of the DAC's input values. Defaults to None. This should be a list
|
|
349
|
+
of probabilities, the first item being the probability of the minimum value, the
|
|
350
|
+
last item being the probability of the maximum value, and the rest being the
|
|
351
|
+
probabilities of the intermediate values.
|
|
352
|
+
load_resistance: float
|
|
353
|
+
The load resistance on the DAC's output. Defaults to 0.
|
|
354
|
+
load_capacitance: float
|
|
355
|
+
The load capacitance on the DAC's output. Defaults to 0.
|
|
356
|
+
|
|
357
|
+
Attributes
|
|
358
|
+
----------
|
|
359
|
+
resolution: int
|
|
360
|
+
The resolution of the DAC.
|
|
361
|
+
voltage: float
|
|
362
|
+
The voltage of the DAC.
|
|
363
|
+
unit_capacitance: float
|
|
364
|
+
The unit capacitance of the DAC.
|
|
365
|
+
tech_node: int
|
|
366
|
+
The tech node of the DAC.
|
|
367
|
+
cycle_period: float, optional
|
|
368
|
+
The cycle period of the clock driving the DAC, and also the minimum time the DAC
|
|
369
|
+
must hold any output values (longer if it takes longer to settle). Defaults to
|
|
370
|
+
1e-9.
|
|
371
|
+
hist: List[float], optional
|
|
372
|
+
The histogram of the DAC's input values. Defaults to None. This should be a list
|
|
373
|
+
of probabilities, the first item being the probability of the minimum value, the
|
|
374
|
+
last item being the probability of the maximum value, and the rest being the
|
|
375
|
+
probabilities of the intermediate values.
|
|
376
|
+
load_resistance: float
|
|
377
|
+
The load resistance on the DAC's output. Defaults to 0.
|
|
378
|
+
load_capacitance: float
|
|
379
|
+
The load capacitance on the DAC's output. Defaults to 0.
|
|
380
|
+
|
|
381
|
+
"""
|
|
382
|
+
|
|
383
|
+
component_name: list[str] = ["C2CLadderDAC", "C2CDAC"]
|
|
384
|
+
|
|
385
|
+
def __init__(
|
|
386
|
+
self,
|
|
387
|
+
resolution: int,
|
|
388
|
+
voltage: float,
|
|
389
|
+
unit_capacitance: float,
|
|
390
|
+
tech_node: int,
|
|
391
|
+
hist: List[float] = None,
|
|
392
|
+
capacitors_consume_area: bool = True,
|
|
393
|
+
cycle_period: float = 1e-9,
|
|
394
|
+
load_capacitance: float = 0,
|
|
395
|
+
load_resistance: float = 0,
|
|
396
|
+
):
|
|
397
|
+
self.unit_capacitance = unit_capacitance
|
|
398
|
+
|
|
399
|
+
self._unit_cap = Capacitor(
|
|
400
|
+
voltage=self.voltage, capacitance=unit_capacitance, tech_node=tech_node
|
|
401
|
+
)
|
|
402
|
+
self._unit2_cap = Capacitor(
|
|
403
|
+
voltage=self.voltage, capacitance=unit_capacitance * 2, tech_node=tech_node
|
|
404
|
+
)
|
|
405
|
+
if not capacitors_consume_area:
|
|
406
|
+
self._unit_cap.area_scale *= 0
|
|
407
|
+
self._unit2_cap.area_scale *= 0
|
|
408
|
+
|
|
409
|
+
super().__init__(
|
|
410
|
+
resolution=resolution,
|
|
411
|
+
voltage=voltage,
|
|
412
|
+
unit_x=unit_capacitance,
|
|
413
|
+
tech_node=tech_node,
|
|
414
|
+
hist=hist,
|
|
415
|
+
load_capacitance=unit_capacitance * 2 + load_capacitance,
|
|
416
|
+
area=self._unit_cap.area + self._unit2_cap.area,
|
|
417
|
+
leak_power=self._unit_cap.leak_power + self._unit2_cap.leak_power,
|
|
418
|
+
kind="C2C",
|
|
419
|
+
load_resistance=load_resistance,
|
|
420
|
+
cycle_period=cycle_period,
|
|
421
|
+
)
|
|
422
|
+
self.scale(
|
|
423
|
+
"resolution",
|
|
424
|
+
resolution,
|
|
425
|
+
1,
|
|
426
|
+
area_scale_function=linear,
|
|
427
|
+
leak_power_scale_function=linear,
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
class R2RLadderDAC(_X2XLadderDAC):
|
|
432
|
+
"""
|
|
433
|
+
R-2R ladder DAC.
|
|
434
|
+
|
|
435
|
+
R-2R ladder and C-2C ladder DACs model those described in the paper: A Charge Domain
|
|
436
|
+
SRAM Compute-in-Memory Macro With C-2C Ladder-Based 8b MAC Unit in 22-nm FinFET
|
|
437
|
+
Process for Edge Inference Wang, Hechen and Liu, Renzhi and Dorrance, Richard and
|
|
438
|
+
Dasalukunte, Deepak and Lake, Dan and Carlton, Brent 10.1109/JSSC.2022.3232601
|
|
439
|
+
|
|
440
|
+
Parameters
|
|
441
|
+
----------
|
|
442
|
+
resolution: int
|
|
443
|
+
The resolution of the DAC.
|
|
444
|
+
voltage: float
|
|
445
|
+
The voltage of the DAC.
|
|
446
|
+
unit_resistance: float
|
|
447
|
+
The unit resistance of the DAC.
|
|
448
|
+
tech_node: int
|
|
449
|
+
The tech node of the DAC.
|
|
450
|
+
cycle_period: float, optional
|
|
451
|
+
The cycle period of the clock driving the DAC, and also the minimum time the DAC
|
|
452
|
+
must hold any output values (longer if it takes longer to settle). Defaults to
|
|
453
|
+
1e-9.
|
|
454
|
+
hist: List[float], optional
|
|
455
|
+
The histogram of the DAC's input values. Defaults to None. This should be a list
|
|
456
|
+
of probabilities, the first item being the probability of the minimum value, the
|
|
457
|
+
last item being the probability of the maximum value, and the rest being the
|
|
458
|
+
probabilities of the intermediate values.
|
|
459
|
+
load_resistance: float
|
|
460
|
+
The load resistance on the DAC's output. Defaults to 0.
|
|
461
|
+
load_capacitance: float
|
|
462
|
+
The load capacitance on the DAC's output. Defaults to 0.
|
|
463
|
+
|
|
464
|
+
Attributes
|
|
465
|
+
----------
|
|
466
|
+
resolution: int
|
|
467
|
+
The resolution of the DAC.
|
|
468
|
+
voltage: float
|
|
469
|
+
The voltage of the DAC.
|
|
470
|
+
unit_resistance: float
|
|
471
|
+
The unit resistance of the DAC.
|
|
472
|
+
tech_node: int
|
|
473
|
+
The tech node of the DAC.
|
|
474
|
+
cycle_period: float, optional
|
|
475
|
+
The cycle period of the clock driving the DAC, and also the minimum time the DAC
|
|
476
|
+
must hold any output values (longer if it takes longer to settle). Defaults to
|
|
477
|
+
1e-9.
|
|
478
|
+
hist: List[float], optional
|
|
479
|
+
The histogram of the DAC's input values. Defaults to None. This should be a list
|
|
480
|
+
of probabilities, the first item being the probability of the minimum value, the
|
|
481
|
+
last item being the probability of the maximum value, and the rest being the
|
|
482
|
+
probabilities of the intermediate values.
|
|
483
|
+
load_resistance: float
|
|
484
|
+
The load resistance on the DAC's output. Defaults to 0.
|
|
485
|
+
load_capacitance: float
|
|
486
|
+
The load capacitance on the DAC's output. Defaults to 0.
|
|
487
|
+
"""
|
|
488
|
+
|
|
489
|
+
component_name: list[str] = ["R2RLadderDAC", "R2RDAC"]
|
|
490
|
+
|
|
491
|
+
def __init__(
|
|
492
|
+
self,
|
|
493
|
+
resolution: int,
|
|
494
|
+
voltage: float,
|
|
495
|
+
unit_resistance: float,
|
|
496
|
+
tech_node: int,
|
|
497
|
+
cycle_period: float = 1e-9,
|
|
498
|
+
hist: List[float] = None,
|
|
499
|
+
load_resistance: float = 0,
|
|
500
|
+
load_capacitance: float = 0,
|
|
501
|
+
):
|
|
502
|
+
self.unit_resistance = unit_resistance
|
|
503
|
+
self._m2_chip_area_per_ohm = 2.35e-15 * (tech_node / 22e-9) ** 2
|
|
504
|
+
|
|
505
|
+
super().__init__(
|
|
506
|
+
resolution=resolution,
|
|
507
|
+
voltage=voltage,
|
|
508
|
+
unit_x=1 / unit_resistance / 2,
|
|
509
|
+
tech_node=tech_node,
|
|
510
|
+
hist=hist,
|
|
511
|
+
area=self._m2_chip_area_per_ohm * resolution * unit_resistance * 3,
|
|
512
|
+
leak_power=0,
|
|
513
|
+
cycle_period=cycle_period,
|
|
514
|
+
kind="R2R",
|
|
515
|
+
load_resistance=load_resistance,
|
|
516
|
+
load_capacitance=load_capacitance,
|
|
517
|
+
)
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
class DualSidedR2RLadderDAC(R2RLadderDAC):
|
|
521
|
+
"""
|
|
522
|
+
Dual-sided R-2R ladder DAC. This DAC has two sides, one for the positive half of the
|
|
523
|
+
voltage range and one for the negative half.
|
|
524
|
+
|
|
525
|
+
R-2R ladder and C-2C ladder DACs model those described in the paper: A Charge Domain
|
|
526
|
+
SRAM Compute-in-Memory Macro With C-2C Ladder-Based 8b MAC Unit in 22-nm FinFET
|
|
527
|
+
Process for Edge Inference Wang, Hechen and Liu, Renzhi and Dorrance, Richard and
|
|
528
|
+
Dasalukunte, Deepak and Lake, Dan and Carlton, Brent 10.1109/JSSC.2022.3232601
|
|
529
|
+
|
|
530
|
+
Parameters
|
|
531
|
+
----------
|
|
532
|
+
resolution: int
|
|
533
|
+
The resolution of the DAC.
|
|
534
|
+
voltage: float
|
|
535
|
+
The voltage of the DAC.
|
|
536
|
+
unit_resistance: float
|
|
537
|
+
The unit resistance of the DAC.
|
|
538
|
+
tech_node: int
|
|
539
|
+
The tech node of the DAC.
|
|
540
|
+
cycle_period: float, optional
|
|
541
|
+
The cycle period of the clock driving the DAC, and also the minimum time the DAC
|
|
542
|
+
must hold any output values (longer if it takes longer to settle). Defaults to
|
|
543
|
+
1e-9.
|
|
544
|
+
hist: List[float], optional
|
|
545
|
+
The histogram of the DAC's input values. Defaults to None. This should be a list
|
|
546
|
+
of probabilities, the first item being the probability of the minimum value, the
|
|
547
|
+
last item being the probability of the maximum value, and the rest being the
|
|
548
|
+
probabilities of the intermediate values.
|
|
549
|
+
load_resistance: float
|
|
550
|
+
The load resistance on the DAC's output. Defaults to 0.
|
|
551
|
+
load_capacitance: float
|
|
552
|
+
The load capacitance on the DAC's output. Defaults to 0.
|
|
553
|
+
|
|
554
|
+
Attributes
|
|
555
|
+
----------
|
|
556
|
+
resolution: int
|
|
557
|
+
The resolution of the DAC.
|
|
558
|
+
voltage: float
|
|
559
|
+
The voltage of the DAC.
|
|
560
|
+
unit_resistance: float
|
|
561
|
+
The unit resistance of the DAC.
|
|
562
|
+
tech_node: int
|
|
563
|
+
The tech node of the DAC.
|
|
564
|
+
cycle_period: float, optional
|
|
565
|
+
The cycle period of the clock driving the DAC, and also the minimum time the DAC
|
|
566
|
+
must hold any output values (longer if it takes longer to settle). Defaults to
|
|
567
|
+
1e-9.
|
|
568
|
+
hist: List[float], optional
|
|
569
|
+
The histogram of the DAC's input values. Defaults to None. This should be a list
|
|
570
|
+
of probabilities, the first item being the probability of the minimum value, the
|
|
571
|
+
last item being the probability of the maximum value, and the rest being the
|
|
572
|
+
probabilities of the intermediate values.
|
|
573
|
+
load_resistance: float
|
|
574
|
+
The load resistance on the DAC's output. Defaults to 0.
|
|
575
|
+
load_capacitance: float
|
|
576
|
+
The load capacitance on the DAC's output. Defaults to 0.
|
|
577
|
+
"""
|
|
578
|
+
|
|
579
|
+
component_name: list[str] = ["DualSidedR2RLadderDAC", "DualSidedR2RDAC"]
|
|
580
|
+
|
|
581
|
+
def __init__(
|
|
582
|
+
self,
|
|
583
|
+
resolution: int,
|
|
584
|
+
voltage: float,
|
|
585
|
+
unit_resistance: float,
|
|
586
|
+
tech_node: int,
|
|
587
|
+
cycle_period: float = 1e-9,
|
|
588
|
+
hist: List[float] = None,
|
|
589
|
+
load_resistance: float = 0,
|
|
590
|
+
load_capacitance: float = 0,
|
|
591
|
+
):
|
|
592
|
+
super().__init__(
|
|
593
|
+
resolution=resolution,
|
|
594
|
+
voltage=voltage,
|
|
595
|
+
unit_resistance=unit_resistance,
|
|
596
|
+
tech_node=tech_node,
|
|
597
|
+
cycle_period=cycle_period,
|
|
598
|
+
hist=hist,
|
|
599
|
+
load_resistance=load_resistance,
|
|
600
|
+
load_capacitance=load_capacitance,
|
|
601
|
+
)
|
|
602
|
+
self.leak_power_scale *= 2 # Two sides
|
|
603
|
+
self.area_scale *= 2 # Two sides
|
|
604
|
+
self.energy_scale *= 2 # Two sides
|
|
605
|
+
# Voltage is still the full range because we're pulling from a VDD supply
|